firebase log level
This commit is contained in:
95
Pods/GoogleDataTransport/GoogleDataTransport/GDTCCTLibrary/GDTCCTCompressionHelper.m
generated
Normal file
95
Pods/GoogleDataTransport/GoogleDataTransport/GDTCCTLibrary/GDTCCTCompressionHelper.m
generated
Normal file
@ -0,0 +1,95 @@
|
||||
/*
|
||||
* Copyright 2020 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#import "GoogleDataTransport/GDTCCTLibrary/Private/GDTCCTCompressionHelper.h"
|
||||
|
||||
#import <zlib.h>
|
||||
|
||||
@implementation GDTCCTCompressionHelper
|
||||
|
||||
+ (nullable NSData *)gzippedData:(NSData *)data {
|
||||
#if defined(__LP64__) && __LP64__
|
||||
// Don't support > 32bit length for 64 bit, see note in header.
|
||||
if (data.length > UINT_MAX) {
|
||||
return nil;
|
||||
}
|
||||
#endif
|
||||
|
||||
enum { kChunkSize = 1024 };
|
||||
|
||||
const void *bytes = [data bytes];
|
||||
NSUInteger length = [data length];
|
||||
|
||||
int level = Z_DEFAULT_COMPRESSION;
|
||||
if (!bytes || !length) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
z_stream strm;
|
||||
bzero(&strm, sizeof(z_stream));
|
||||
|
||||
int memLevel = 8; // Default.
|
||||
int windowBits = 15 + 16; // Enable gzip header instead of zlib header.
|
||||
|
||||
int retCode;
|
||||
if (deflateInit2(&strm, level, Z_DEFLATED, windowBits, memLevel, Z_DEFAULT_STRATEGY) != Z_OK) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
// Hint the size at 1/4 the input size.
|
||||
NSMutableData *result = [NSMutableData dataWithCapacity:(length / 4)];
|
||||
unsigned char output[kChunkSize];
|
||||
|
||||
// Setup the input.
|
||||
strm.avail_in = (unsigned int)length;
|
||||
strm.next_in = (unsigned char *)bytes;
|
||||
|
||||
// Collect the data.
|
||||
do {
|
||||
// update what we're passing in
|
||||
strm.avail_out = kChunkSize;
|
||||
strm.next_out = output;
|
||||
retCode = deflate(&strm, Z_FINISH);
|
||||
if ((retCode != Z_OK) && (retCode != Z_STREAM_END)) {
|
||||
deflateEnd(&strm);
|
||||
return nil;
|
||||
}
|
||||
// Collect what we got.
|
||||
unsigned gotBack = kChunkSize - strm.avail_out;
|
||||
if (gotBack > 0) {
|
||||
[result appendBytes:output length:gotBack];
|
||||
}
|
||||
|
||||
} while (retCode == Z_OK);
|
||||
|
||||
// If the loop exits, it used all input and the stream ended.
|
||||
NSAssert(strm.avail_in == 0,
|
||||
@"Should have finished deflating without using all input, %u bytes left", strm.avail_in);
|
||||
NSAssert(retCode == Z_STREAM_END,
|
||||
@"thought we finished deflate w/o getting a result of stream end, code %d", retCode);
|
||||
|
||||
// Clean up.
|
||||
deflateEnd(&strm);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
+ (BOOL)isGzipped:(NSData *)data {
|
||||
const UInt8 *bytes = (const UInt8 *)data.bytes;
|
||||
return (data.length >= 2 && bytes[0] == 0x1f && bytes[1] == 0x8b);
|
||||
}
|
||||
|
||||
@end
|
||||
322
Pods/GoogleDataTransport/GoogleDataTransport/GDTCCTLibrary/GDTCCTNanopbHelpers.m
generated
Normal file
322
Pods/GoogleDataTransport/GoogleDataTransport/GDTCCTLibrary/GDTCCTNanopbHelpers.m
generated
Normal file
@ -0,0 +1,322 @@
|
||||
/*
|
||||
* Copyright 2019 Google
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#import "GoogleDataTransport/GDTCCTLibrary/Private/GDTCCTNanopbHelpers.h"
|
||||
|
||||
#if TARGET_OS_IOS || TARGET_OS_TV
|
||||
#import <UIKit/UIKit.h>
|
||||
#elif TARGET_OS_OSX
|
||||
#import <AppKit/AppKit.h>
|
||||
#endif // TARGET_OS_IOS || TARGET_OS_TV
|
||||
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Internal/GDTCORPlatform.h"
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORClock.h"
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORConsoleLogger.h"
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCOREvent.h"
|
||||
|
||||
#import <nanopb/pb.h>
|
||||
#import <nanopb/pb_decode.h>
|
||||
#import <nanopb/pb_encode.h>
|
||||
|
||||
#import "GoogleDataTransport/GDTCCTLibrary/Public/GDTCOREvent+GDTCCTSupport.h"
|
||||
|
||||
#pragma mark - General purpose encoders
|
||||
|
||||
pb_bytes_array_t *GDTCCTEncodeString(NSString *string) {
|
||||
NSData *stringBytes = [string dataUsingEncoding:NSUTF8StringEncoding];
|
||||
return GDTCCTEncodeData(stringBytes);
|
||||
}
|
||||
|
||||
pb_bytes_array_t *GDTCCTEncodeData(NSData *data) {
|
||||
pb_bytes_array_t *pbBytesArray = calloc(1, PB_BYTES_ARRAY_T_ALLOCSIZE(data.length));
|
||||
if (pbBytesArray != NULL) {
|
||||
[data getBytes:pbBytesArray->bytes length:data.length];
|
||||
pbBytesArray->size = (pb_size_t)data.length;
|
||||
}
|
||||
return pbBytesArray;
|
||||
}
|
||||
|
||||
#pragma mark - CCT object constructors
|
||||
|
||||
NSData *_Nullable GDTCCTEncodeBatchedLogRequest(gdt_cct_BatchedLogRequest *batchedLogRequest) {
|
||||
pb_ostream_t sizestream = PB_OSTREAM_SIZING;
|
||||
// Encode 1 time to determine the size.
|
||||
if (!pb_encode(&sizestream, gdt_cct_BatchedLogRequest_fields, batchedLogRequest)) {
|
||||
GDTCORLogError(GDTCORMCEGeneralError, @"Error in nanopb encoding for size: %s",
|
||||
PB_GET_ERROR(&sizestream));
|
||||
}
|
||||
|
||||
// Encode a 2nd time to actually get the bytes from it.
|
||||
size_t bufferSize = sizestream.bytes_written;
|
||||
CFMutableDataRef dataRef = CFDataCreateMutable(CFAllocatorGetDefault(), bufferSize);
|
||||
CFDataSetLength(dataRef, bufferSize);
|
||||
pb_ostream_t ostream = pb_ostream_from_buffer((void *)CFDataGetBytePtr(dataRef), bufferSize);
|
||||
if (!pb_encode(&ostream, gdt_cct_BatchedLogRequest_fields, batchedLogRequest)) {
|
||||
GDTCORLogError(GDTCORMCEGeneralError, @"Error in nanopb encoding for bytes: %s",
|
||||
PB_GET_ERROR(&ostream));
|
||||
}
|
||||
|
||||
return CFBridgingRelease(dataRef);
|
||||
}
|
||||
|
||||
gdt_cct_BatchedLogRequest GDTCCTConstructBatchedLogRequest(
|
||||
NSDictionary<NSString *, NSSet<GDTCOREvent *> *> *logMappingIDToLogSet) {
|
||||
gdt_cct_BatchedLogRequest batchedLogRequest = gdt_cct_BatchedLogRequest_init_default;
|
||||
NSUInteger numberOfLogRequests = logMappingIDToLogSet.count;
|
||||
gdt_cct_LogRequest *logRequests = calloc(numberOfLogRequests, sizeof(gdt_cct_LogRequest));
|
||||
if (logRequests == NULL) {
|
||||
return batchedLogRequest;
|
||||
}
|
||||
|
||||
__block int i = 0;
|
||||
[logMappingIDToLogSet enumerateKeysAndObjectsUsingBlock:^(NSString *_Nonnull logMappingID,
|
||||
NSSet<GDTCOREvent *> *_Nonnull logSet,
|
||||
BOOL *_Nonnull stop) {
|
||||
int32_t logSource = [logMappingID intValue];
|
||||
gdt_cct_LogRequest logRequest = GDTCCTConstructLogRequest(logSource, logSet);
|
||||
logRequests[i] = logRequest;
|
||||
i++;
|
||||
}];
|
||||
|
||||
batchedLogRequest.log_request = logRequests;
|
||||
batchedLogRequest.log_request_count = (pb_size_t)numberOfLogRequests;
|
||||
return batchedLogRequest;
|
||||
}
|
||||
|
||||
gdt_cct_LogRequest GDTCCTConstructLogRequest(int32_t logSource,
|
||||
NSSet<GDTCOREvent *> *_Nonnull logSet) {
|
||||
if (logSet.count == 0) {
|
||||
GDTCORLogError(GDTCORMCEGeneralError, @"%@",
|
||||
@"An empty event set can't be serialized to proto.");
|
||||
gdt_cct_LogRequest logRequest = gdt_cct_LogRequest_init_default;
|
||||
return logRequest;
|
||||
}
|
||||
gdt_cct_LogRequest logRequest = gdt_cct_LogRequest_init_default;
|
||||
logRequest.log_source = logSource;
|
||||
logRequest.has_log_source = 1;
|
||||
logRequest.client_info = GDTCCTConstructClientInfo();
|
||||
logRequest.has_client_info = 1;
|
||||
logRequest.log_event = calloc(logSet.count, sizeof(gdt_cct_LogEvent));
|
||||
if (logRequest.log_event == NULL) {
|
||||
return logRequest;
|
||||
}
|
||||
int i = 0;
|
||||
for (GDTCOREvent *log in logSet) {
|
||||
gdt_cct_LogEvent logEvent = GDTCCTConstructLogEvent(log);
|
||||
logRequest.log_event[i] = logEvent;
|
||||
i++;
|
||||
}
|
||||
logRequest.log_event_count = (pb_size_t)logSet.count;
|
||||
|
||||
GDTCORClock *currentTime = [GDTCORClock snapshot];
|
||||
logRequest.request_time_ms = currentTime.timeMillis;
|
||||
logRequest.has_request_time_ms = 1;
|
||||
logRequest.request_uptime_ms = [currentTime uptimeMilliseconds];
|
||||
logRequest.has_request_uptime_ms = 1;
|
||||
|
||||
return logRequest;
|
||||
}
|
||||
|
||||
gdt_cct_LogEvent GDTCCTConstructLogEvent(GDTCOREvent *event) {
|
||||
gdt_cct_LogEvent logEvent = gdt_cct_LogEvent_init_default;
|
||||
logEvent.event_time_ms = event.clockSnapshot.timeMillis;
|
||||
logEvent.has_event_time_ms = 1;
|
||||
logEvent.event_uptime_ms = [event.clockSnapshot uptimeMilliseconds];
|
||||
logEvent.has_event_uptime_ms = 1;
|
||||
logEvent.timezone_offset_seconds = event.clockSnapshot.timezoneOffsetSeconds;
|
||||
logEvent.has_timezone_offset_seconds = 1;
|
||||
if (event.customBytes) {
|
||||
NSData *networkConnectionInfoData = event.networkConnectionInfoData;
|
||||
if (networkConnectionInfoData) {
|
||||
[networkConnectionInfoData getBytes:&logEvent.network_connection_info
|
||||
length:networkConnectionInfoData.length];
|
||||
logEvent.has_network_connection_info = 1;
|
||||
}
|
||||
NSNumber *eventCode = event.eventCode;
|
||||
if (eventCode != nil) {
|
||||
logEvent.has_event_code = 1;
|
||||
logEvent.event_code = [eventCode intValue];
|
||||
}
|
||||
}
|
||||
NSError *error;
|
||||
NSData *extensionBytes;
|
||||
extensionBytes = event.serializedDataObjectBytes;
|
||||
if (error) {
|
||||
GDTCORLogWarning(GDTCORMCWFileReadError,
|
||||
@"There was an error reading extension bytes from disk: %@", error);
|
||||
return logEvent;
|
||||
}
|
||||
logEvent.source_extension = GDTCCTEncodeData(extensionBytes); // read bytes from the file.
|
||||
if (event.productData) {
|
||||
logEvent.compliance_data = GDTCCTConstructComplianceData(event.productData);
|
||||
logEvent.has_compliance_data = 1;
|
||||
}
|
||||
return logEvent;
|
||||
}
|
||||
|
||||
gdt_cct_ComplianceData GDTCCTConstructComplianceData(GDTCORProductData *productData) {
|
||||
privacy_context_external_ExternalPRequestContext prequest =
|
||||
privacy_context_external_ExternalPRequestContext_init_default;
|
||||
prequest.origin_associated_product_id = productData.productID;
|
||||
prequest.has_origin_associated_product_id = 1;
|
||||
|
||||
privacy_context_external_ExternalPrivacyContext privacy_context =
|
||||
privacy_context_external_ExternalPrivacyContext_init_default;
|
||||
privacy_context.prequest = prequest;
|
||||
privacy_context.has_prequest = 1;
|
||||
|
||||
gdt_cct_ComplianceData complianceData = gdt_cct_ComplianceData_init_default;
|
||||
complianceData.privacy_context = privacy_context;
|
||||
complianceData.has_privacy_context = 1;
|
||||
complianceData.product_id_origin = gdt_cct_ComplianceData_ProductIdOrigin_EVENT_OVERRIDE;
|
||||
complianceData.has_product_id_origin = 1;
|
||||
return complianceData;
|
||||
}
|
||||
|
||||
gdt_cct_ClientInfo GDTCCTConstructClientInfo(void) {
|
||||
gdt_cct_ClientInfo clientInfo = gdt_cct_ClientInfo_init_default;
|
||||
clientInfo.client_type = gdt_cct_ClientInfo_ClientType_IOS_FIREBASE;
|
||||
clientInfo.has_client_type = 1;
|
||||
#if TARGET_OS_IOS || TARGET_OS_TV
|
||||
clientInfo.ios_client_info = GDTCCTConstructiOSClientInfo();
|
||||
clientInfo.has_ios_client_info = 1;
|
||||
#elif TARGET_OS_OSX
|
||||
clientInfo.mac_client_info = GDTCCTConstructMacClientInfo();
|
||||
clientInfo.has_mac_client_info = 1;
|
||||
#endif
|
||||
return clientInfo;
|
||||
}
|
||||
|
||||
gdt_cct_IosClientInfo GDTCCTConstructiOSClientInfo(void) {
|
||||
gdt_cct_IosClientInfo iOSClientInfo = gdt_cct_IosClientInfo_init_default;
|
||||
#if TARGET_OS_IOS || TARGET_OS_TV
|
||||
UIDevice *device = [UIDevice currentDevice];
|
||||
NSBundle *bundle = [NSBundle mainBundle];
|
||||
NSLocale *locale = [NSLocale currentLocale];
|
||||
iOSClientInfo.os_full_version = GDTCCTEncodeString(device.systemVersion);
|
||||
NSArray *versionComponents = [device.systemVersion componentsSeparatedByString:@"."];
|
||||
iOSClientInfo.os_major_version = GDTCCTEncodeString(versionComponents[0]);
|
||||
NSString *version = [bundle objectForInfoDictionaryKey:(NSString *)kCFBundleVersionKey];
|
||||
if (version) {
|
||||
iOSClientInfo.application_build = GDTCCTEncodeString(version);
|
||||
}
|
||||
NSString *countryCode = [locale objectForKey:NSLocaleCountryCode];
|
||||
if (countryCode) {
|
||||
iOSClientInfo.country = GDTCCTEncodeString([locale objectForKey:NSLocaleCountryCode]);
|
||||
}
|
||||
iOSClientInfo.model = GDTCCTEncodeString(GDTCORDeviceModel());
|
||||
NSString *languageCode = bundle.preferredLocalizations.firstObject;
|
||||
iOSClientInfo.language_code =
|
||||
languageCode ? GDTCCTEncodeString(languageCode) : GDTCCTEncodeString(@"en");
|
||||
iOSClientInfo.application_bundle_id = GDTCCTEncodeString(bundle.bundleIdentifier);
|
||||
#endif
|
||||
return iOSClientInfo;
|
||||
}
|
||||
|
||||
gdt_cct_MacClientInfo GDTCCTConstructMacClientInfo(void) {
|
||||
gdt_cct_MacClientInfo macOSClientInfo = gdt_cct_MacClientInfo_init_default;
|
||||
|
||||
NSOperatingSystemVersion osVersion = [NSProcessInfo processInfo].operatingSystemVersion;
|
||||
NSString *majorVersion = [@(osVersion.majorVersion) stringValue];
|
||||
NSString *minorVersion = [@(osVersion.minorVersion) stringValue];
|
||||
NSString *majorAndMinorString = [NSString stringWithFormat:@"%@.%@", majorVersion, minorVersion];
|
||||
macOSClientInfo.os_major_version = GDTCCTEncodeString(majorAndMinorString);
|
||||
|
||||
NSString *patchVersion = [@(osVersion.patchVersion) stringValue];
|
||||
NSString *majorMinorPatchString =
|
||||
[NSString stringWithFormat:@"%@.%@", majorAndMinorString, patchVersion];
|
||||
macOSClientInfo.os_full_version = GDTCCTEncodeString(majorMinorPatchString);
|
||||
|
||||
NSBundle *bundle = [NSBundle mainBundle];
|
||||
NSString *version = [bundle objectForInfoDictionaryKey:(NSString *)kCFBundleVersionKey];
|
||||
if (version) {
|
||||
macOSClientInfo.application_build = GDTCCTEncodeString(version);
|
||||
}
|
||||
|
||||
NSString *bundleID = bundle.bundleIdentifier;
|
||||
if (bundleID) {
|
||||
macOSClientInfo.application_bundle_id = GDTCCTEncodeString(bundleID);
|
||||
}
|
||||
|
||||
return macOSClientInfo;
|
||||
}
|
||||
|
||||
NSData *GDTCCTConstructNetworkConnectionInfoData(void) {
|
||||
gdt_cct_NetworkConnectionInfo networkConnectionInfo = gdt_cct_NetworkConnectionInfo_init_default;
|
||||
NSInteger currentNetworkType = GDTCORNetworkTypeMessage();
|
||||
if (currentNetworkType) {
|
||||
networkConnectionInfo.has_network_type = 1;
|
||||
if (currentNetworkType == GDTCORNetworkTypeMobile) {
|
||||
networkConnectionInfo.network_type = gdt_cct_NetworkConnectionInfo_NetworkType_MOBILE;
|
||||
networkConnectionInfo.mobile_subtype = GDTCCTNetworkConnectionInfoNetworkMobileSubtype();
|
||||
if (networkConnectionInfo.mobile_subtype !=
|
||||
gdt_cct_NetworkConnectionInfo_MobileSubtype_UNKNOWN_MOBILE_SUBTYPE) {
|
||||
networkConnectionInfo.has_mobile_subtype = 1;
|
||||
}
|
||||
} else {
|
||||
networkConnectionInfo.network_type = gdt_cct_NetworkConnectionInfo_NetworkType_WIFI;
|
||||
}
|
||||
}
|
||||
NSData *networkConnectionInfoData = [NSData dataWithBytes:&networkConnectionInfo
|
||||
length:sizeof(networkConnectionInfo)];
|
||||
return networkConnectionInfoData;
|
||||
}
|
||||
|
||||
gdt_cct_NetworkConnectionInfo_MobileSubtype GDTCCTNetworkConnectionInfoNetworkMobileSubtype(void) {
|
||||
NSNumber *networkMobileSubtypeMessage = @(GDTCORNetworkMobileSubTypeMessage());
|
||||
if (!networkMobileSubtypeMessage.intValue) {
|
||||
return gdt_cct_NetworkConnectionInfo_MobileSubtype_UNKNOWN_MOBILE_SUBTYPE;
|
||||
}
|
||||
static NSDictionary<NSNumber *, NSNumber *> *MessageToNetworkSubTypeMessage;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
MessageToNetworkSubTypeMessage = @{
|
||||
@(GDTCORNetworkMobileSubtypeGPRS) : @(gdt_cct_NetworkConnectionInfo_MobileSubtype_GPRS),
|
||||
@(GDTCORNetworkMobileSubtypeEdge) : @(gdt_cct_NetworkConnectionInfo_MobileSubtype_EDGE),
|
||||
@(GDTCORNetworkMobileSubtypeWCDMA) :
|
||||
@(gdt_cct_NetworkConnectionInfo_MobileSubtype_UNKNOWN_MOBILE_SUBTYPE),
|
||||
@(GDTCORNetworkMobileSubtypeHSDPA) : @(gdt_cct_NetworkConnectionInfo_MobileSubtype_HSDPA),
|
||||
@(GDTCORNetworkMobileSubtypeHSUPA) : @(gdt_cct_NetworkConnectionInfo_MobileSubtype_HSUPA),
|
||||
@(GDTCORNetworkMobileSubtypeCDMA1x) : @(gdt_cct_NetworkConnectionInfo_MobileSubtype_CDMA),
|
||||
@(GDTCORNetworkMobileSubtypeCDMAEVDORev0) :
|
||||
@(gdt_cct_NetworkConnectionInfo_MobileSubtype_EVDO_0),
|
||||
@(GDTCORNetworkMobileSubtypeCDMAEVDORevA) :
|
||||
@(gdt_cct_NetworkConnectionInfo_MobileSubtype_EVDO_A),
|
||||
@(GDTCORNetworkMobileSubtypeCDMAEVDORevB) :
|
||||
@(gdt_cct_NetworkConnectionInfo_MobileSubtype_EVDO_B),
|
||||
@(GDTCORNetworkMobileSubtypeHRPD) : @(gdt_cct_NetworkConnectionInfo_MobileSubtype_EHRPD),
|
||||
@(GDTCORNetworkMobileSubtypeLTE) : @(gdt_cct_NetworkConnectionInfo_MobileSubtype_LTE),
|
||||
};
|
||||
});
|
||||
NSNumber *networkMobileSubtype = MessageToNetworkSubTypeMessage[networkMobileSubtypeMessage];
|
||||
return networkMobileSubtype.intValue;
|
||||
}
|
||||
|
||||
#pragma mark - CCT Object decoders
|
||||
|
||||
gdt_cct_LogResponse GDTCCTDecodeLogResponse(NSData *data, NSError **error) {
|
||||
gdt_cct_LogResponse response = gdt_cct_LogResponse_init_default;
|
||||
pb_istream_t istream = pb_istream_from_buffer([data bytes], [data length]);
|
||||
if (!pb_decode(&istream, gdt_cct_LogResponse_fields, &response)) {
|
||||
NSString *nanopb_error = [NSString stringWithFormat:@"%s", PB_GET_ERROR(&istream)];
|
||||
NSDictionary *userInfo = @{@"nanopb error:" : nanopb_error};
|
||||
if (error != NULL) {
|
||||
*error = [NSError errorWithDomain:NSURLErrorDomain code:-1 userInfo:userInfo];
|
||||
}
|
||||
response = (gdt_cct_LogResponse)gdt_cct_LogResponse_init_default;
|
||||
}
|
||||
return response;
|
||||
}
|
||||
28
Pods/GoogleDataTransport/GoogleDataTransport/GDTCCTLibrary/GDTCCTURLSessionDataResponse.m
generated
Normal file
28
Pods/GoogleDataTransport/GoogleDataTransport/GDTCCTLibrary/GDTCCTURLSessionDataResponse.m
generated
Normal file
@ -0,0 +1,28 @@
|
||||
// Copyright 2024 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#import "GoogleDataTransport/GDTCCTLibrary/Private/GDTCCTURLSessionDataResponse.h"
|
||||
|
||||
@implementation GDTCCTURLSessionDataResponse
|
||||
|
||||
- (instancetype)initWithResponse:(NSHTTPURLResponse *)response HTTPBody:(NSData *)body {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_HTTPResponse = response;
|
||||
_HTTPBody = body;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
||||
668
Pods/GoogleDataTransport/GoogleDataTransport/GDTCCTLibrary/GDTCCTUploadOperation.m
generated
Normal file
668
Pods/GoogleDataTransport/GoogleDataTransport/GDTCCTLibrary/GDTCCTUploadOperation.m
generated
Normal file
@ -0,0 +1,668 @@
|
||||
/*
|
||||
* Copyright 2020 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#import "GoogleDataTransport/GDTCCTLibrary/Private/GDTCCTUploadOperation.h"
|
||||
|
||||
#if __has_include(<FBLPromises/FBLPromises.h>)
|
||||
#import <FBLPromises/FBLPromises.h>
|
||||
#else
|
||||
#import "FBLPromises.h"
|
||||
#endif
|
||||
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Internal/GDTCORPlatform.h"
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Internal/GDTCORRegistrar.h"
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Internal/GDTCORStorageProtocol.h"
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Private/GDTCORMetrics.h"
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Private/GDTCORUploadBatch.h"
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORConsoleLogger.h"
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCOREvent.h"
|
||||
|
||||
#import <nanopb/pb.h>
|
||||
#import <nanopb/pb_decode.h>
|
||||
#import <nanopb/pb_encode.h>
|
||||
|
||||
#import "GoogleDataTransport/GDTCCTLibrary/Private/GDTCCTCompressionHelper.h"
|
||||
#import "GoogleDataTransport/GDTCCTLibrary/Private/GDTCCTNanopbHelpers.h"
|
||||
#import "GoogleDataTransport/GDTCCTLibrary/Private/GDTCCTURLSessionDataResponse.h"
|
||||
#import "GoogleDataTransport/GDTCCTLibrary/Private/GDTCOREvent+GDTMetricsSupport.h"
|
||||
|
||||
#import "GoogleDataTransport/GDTCCTLibrary/Protogen/nanopb/cct.nanopb.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
#ifdef GDTCOR_VERSION
|
||||
#define STR(x) STR_EXPAND(x)
|
||||
#define STR_EXPAND(x) #x
|
||||
static NSString *const kGDTCCTSupportSDKVersion = @STR(GDTCOR_VERSION);
|
||||
#else
|
||||
static NSString *const kGDTCCTSupportSDKVersion = @"UNKNOWN";
|
||||
#endif // GDTCOR_VERSION
|
||||
|
||||
typedef void (^GDTCCTUploaderURLTaskCompletion)(NSNumber *batchID,
|
||||
NSSet<GDTCOREvent *> *_Nullable events,
|
||||
NSData *_Nullable data,
|
||||
NSURLResponse *_Nullable response,
|
||||
NSError *_Nullable error);
|
||||
|
||||
typedef void (^GDTCCTUploaderEventBatchBlock)(NSNumber *_Nullable batchID,
|
||||
NSSet<GDTCOREvent *> *_Nullable events);
|
||||
|
||||
@interface GDTCCTUploadOperation () <NSURLSessionDelegate>
|
||||
|
||||
/// The properties to store parameters passed in the initializer. See the initialized docs for
|
||||
/// details.
|
||||
@property(nonatomic, readonly) GDTCORTarget target;
|
||||
@property(nonatomic, readonly) GDTCORUploadConditions conditions;
|
||||
@property(nonatomic, readonly) NSURL *uploadURL;
|
||||
@property(nonatomic, readonly) id<GDTCORStoragePromiseProtocol> storage;
|
||||
@property(nonatomic, readonly) id<GDTCCTUploadMetadataProvider> metadataProvider;
|
||||
@property(nonatomic, readonly, nullable) id<GDTCORMetricsControllerProtocol> metricsController;
|
||||
|
||||
/** The URL session that will attempt upload. */
|
||||
@property(nonatomic, nullable) NSURLSession *uploaderSession;
|
||||
|
||||
/// The metrics being uploaded by the operation. These metrics are fetched and included as an event
|
||||
/// in the upload batch as part of the upload process.
|
||||
///
|
||||
/// Metrics being uploaded are retained so they can be re-stored if upload is not successful.
|
||||
@property(nonatomic, nullable) GDTCORMetrics *currentMetrics;
|
||||
|
||||
/// NSOperation state properties implementation.
|
||||
@property(nonatomic, readwrite, getter=isExecuting) BOOL executing;
|
||||
@property(nonatomic, readwrite, getter=isFinished) BOOL finished;
|
||||
|
||||
@property(nonatomic, readwrite) BOOL uploadAttempted;
|
||||
|
||||
@end
|
||||
|
||||
@implementation GDTCCTUploadOperation
|
||||
|
||||
- (instancetype)initWithTarget:(GDTCORTarget)target
|
||||
conditions:(GDTCORUploadConditions)conditions
|
||||
uploadURL:(NSURL *)uploadURL
|
||||
queue:(dispatch_queue_t)queue
|
||||
storage:(id<GDTCORStoragePromiseProtocol>)storage
|
||||
metadataProvider:(id<GDTCCTUploadMetadataProvider>)metadataProvider
|
||||
metricsController:(nullable id<GDTCORMetricsControllerProtocol>)metricsController {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_uploaderQueue = queue;
|
||||
_target = target;
|
||||
_conditions = conditions;
|
||||
_uploadURL = uploadURL;
|
||||
_storage = storage;
|
||||
_metadataProvider = metadataProvider;
|
||||
_metricsController = metricsController;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (NSURLSession *)uploaderSessionCreateIfNeeded {
|
||||
if (_uploaderSession == nil) {
|
||||
NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
|
||||
_uploaderSession = [NSURLSession sessionWithConfiguration:config
|
||||
delegate:self
|
||||
delegateQueue:nil];
|
||||
}
|
||||
return _uploaderSession;
|
||||
}
|
||||
|
||||
- (void)uploadTarget:(GDTCORTarget)target withConditions:(GDTCORUploadConditions)conditions {
|
||||
__block GDTCORBackgroundIdentifier backgroundTaskID = GDTCORBackgroundIdentifierInvalid;
|
||||
|
||||
dispatch_block_t backgroundTaskCompletion = ^{
|
||||
// End the background task if there was one.
|
||||
if (backgroundTaskID != GDTCORBackgroundIdentifierInvalid) {
|
||||
[[GDTCORApplication sharedApplication] endBackgroundTask:backgroundTaskID];
|
||||
backgroundTaskID = GDTCORBackgroundIdentifierInvalid;
|
||||
}
|
||||
};
|
||||
|
||||
backgroundTaskID = [[GDTCORApplication sharedApplication]
|
||||
beginBackgroundTaskWithName:@"GDTCCTUploader-upload"
|
||||
expirationHandler:^{
|
||||
if (backgroundTaskID != GDTCORBackgroundIdentifierInvalid) {
|
||||
// Cancel the upload and complete delivery.
|
||||
[self.currentTask cancel];
|
||||
|
||||
// End the background task.
|
||||
backgroundTaskCompletion();
|
||||
} else {
|
||||
GDTCORLog(GDTCORMCDDebugLog, GDTCORLoggingLevelWarnings,
|
||||
@"Attempted to cancel invalid background task in "
|
||||
"GDTCCTUploadOperation.");
|
||||
}
|
||||
}];
|
||||
|
||||
id<GDTCORStoragePromiseProtocol> storage = self.storage;
|
||||
|
||||
// 1. Check if the conditions for the target are suitable.
|
||||
[self isReadyToUploadTarget:target conditions:conditions]
|
||||
.validateOn(self.uploaderQueue,
|
||||
^BOOL(NSNull *__unused _) {
|
||||
// 2. Stop the operation if it has been cancelled.
|
||||
return !self.isCancelled;
|
||||
})
|
||||
.thenOn(self.uploaderQueue,
|
||||
^FBLPromise *(NSNull *result) {
|
||||
// 3. Remove previously attempted batches.
|
||||
return [storage removeAllBatchesForTarget:target deleteEvents:NO];
|
||||
})
|
||||
.thenOn(self.uploaderQueue,
|
||||
^FBLPromise<NSNumber *> *(NSNull *__unused _) {
|
||||
// There may be a big amount of events stored, so creating a batch may be an
|
||||
// expensive operation.
|
||||
|
||||
// 4. Do a lightweight check if there are any events for the target first to
|
||||
// finish early if there are none.
|
||||
return [storage hasEventsForTarget:target];
|
||||
})
|
||||
.validateOn(self.uploaderQueue,
|
||||
^BOOL(NSNumber *hasEvents) {
|
||||
// 5. Stop operation if there are no events to upload.
|
||||
return hasEvents.boolValue;
|
||||
})
|
||||
.thenOn(self.uploaderQueue,
|
||||
^FBLPromise<GDTCORUploadBatch *> *(NSNumber *__unused _) {
|
||||
// 6. Fetch events to upload.
|
||||
GDTCORStorageEventSelector *eventSelector = [self eventSelectorTarget:target
|
||||
withConditions:conditions];
|
||||
return [storage batchWithEventSelector:eventSelector
|
||||
batchExpiration:[NSDate dateWithTimeIntervalSinceNow:600]];
|
||||
})
|
||||
.thenOn(self.uploaderQueue,
|
||||
^FBLPromise<GDTCORUploadBatch *> *(GDTCORUploadBatch *batch) {
|
||||
// 7. Add metrics to the batch if the target has a
|
||||
// corresponding metrics controller.
|
||||
if (!self.metricsController) {
|
||||
return [FBLPromise resolvedWith:batch];
|
||||
}
|
||||
|
||||
return [self batchByAddingMetricsEventToBatch:batch forTarget:target];
|
||||
})
|
||||
.validateOn(self.uploaderQueue,
|
||||
^BOOL(GDTCORUploadBatch *__unused _) {
|
||||
// 8. Stop the operation if it has been cancelled.
|
||||
return !self.isCancelled;
|
||||
})
|
||||
.thenOn(self.uploaderQueue,
|
||||
^FBLPromise *(GDTCORUploadBatch *batch) {
|
||||
// A non-empty batch has been created, consider it as an upload attempt.
|
||||
self.uploadAttempted = YES;
|
||||
|
||||
// 9. Perform upload.
|
||||
return [self uploadBatch:batch toTarget:target storage:storage];
|
||||
})
|
||||
.catchOn(self.uploaderQueue,
|
||||
^(NSError *error){
|
||||
// TODO: Consider reporting the error to the client.
|
||||
})
|
||||
.alwaysOn(self.uploaderQueue, ^{
|
||||
// 10. Finish operation.
|
||||
[self finishOperation];
|
||||
backgroundTaskCompletion();
|
||||
});
|
||||
}
|
||||
|
||||
#pragma mark - Upload implementation details
|
||||
|
||||
/** Uploads a given batch from storage to a target. */
|
||||
- (FBLPromise<NSNull *> *)uploadBatch:(GDTCORUploadBatch *)batch
|
||||
toTarget:(GDTCORTarget)target
|
||||
storage:(id<GDTCORStoragePromiseProtocol>)storage {
|
||||
// 1. Send URL request.
|
||||
return [self sendURLRequestWithBatch:batch target:target]
|
||||
.thenOn(self.uploaderQueue,
|
||||
^FBLPromise *(GDTCCTURLSessionDataResponse *response) {
|
||||
// 2. Update the next upload time and process response.
|
||||
[self updateNextUploadTimeWithResponse:response forTarget:target];
|
||||
|
||||
return [self processResponse:response forBatch:batch storage:storage];
|
||||
})
|
||||
.recoverOn(self.uploaderQueue, ^id(NSError *error) {
|
||||
// If a network error occurred, move the events back to the main
|
||||
// storage so they can attempt to be uploaded in the next attempt.
|
||||
// Additionally, if metrics were added to the batch, place them back
|
||||
// in storage.
|
||||
if (self.currentMetrics) {
|
||||
[self.metricsController offerMetrics:self.currentMetrics];
|
||||
}
|
||||
return [storage removeBatchWithID:batch.batchID deleteEvents:NO];
|
||||
});
|
||||
}
|
||||
|
||||
/** Processes a URL session response for a given batch from storage. */
|
||||
- (FBLPromise<NSNull *> *)processResponse:(GDTCCTURLSessionDataResponse *)response
|
||||
forBatch:(GDTCORUploadBatch *)batch
|
||||
storage:(id<GDTCORStoragePromiseProtocol>)storage {
|
||||
// Cleanup batch based on the response's status code.
|
||||
NSInteger statusCode = response.HTTPResponse.statusCode;
|
||||
BOOL isSuccess = statusCode >= 200 && statusCode < 300;
|
||||
// Transient errors include "too many requests" (429) and server errors (5xx).
|
||||
BOOL isTransientError =
|
||||
statusCode == 429 || statusCode == 404 || (statusCode >= 500 && statusCode < 600);
|
||||
|
||||
BOOL shouldDeleteEvents = isSuccess || !isTransientError;
|
||||
|
||||
// If the batch included metrics and the upload failed, place metrics back
|
||||
// in storage.
|
||||
GDTCORMetrics *uploadedMetrics = [self currentMetrics];
|
||||
if (uploadedMetrics && !isSuccess) {
|
||||
[self.metricsController offerMetrics:uploadedMetrics];
|
||||
}
|
||||
|
||||
if (isSuccess) {
|
||||
GDTCORLogDebug(@"CCT: batch %@ uploaded. Batch will be deleted.", batch.batchID);
|
||||
|
||||
} else if (isTransientError) {
|
||||
GDTCORLogDebug(@"CCT: batch %@ upload failed. Batch will attempt to be uploaded later.",
|
||||
batch.batchID);
|
||||
|
||||
} else {
|
||||
GDTCORLogDebug(@"CCT: batch %@ upload failed. Batch will be deleted.", batch.batchID);
|
||||
|
||||
if (/* isInvalidPayloadError */ statusCode == 400) {
|
||||
// Log events that will be dropped due to the upload error.
|
||||
[self.metricsController logEventsDroppedForReason:GDTCOREventDropReasonInvalidPayload
|
||||
events:batch.events];
|
||||
}
|
||||
}
|
||||
|
||||
return [storage removeBatchWithID:batch.batchID deleteEvents:shouldDeleteEvents];
|
||||
}
|
||||
|
||||
/** Composes and sends URL request. */
|
||||
- (FBLPromise<GDTCCTURLSessionDataResponse *> *)sendURLRequestWithBatch:(GDTCORUploadBatch *)batch
|
||||
target:(GDTCORTarget)target {
|
||||
return [FBLPromise
|
||||
onQueue:self.uploaderQueue
|
||||
do:^NSURLRequest * {
|
||||
// 1. Prepare URL request.
|
||||
NSData *requestProtoData = [self constructRequestProtoWithEvents:batch.events];
|
||||
NSData *gzippedData = [GDTCCTCompressionHelper gzippedData:requestProtoData];
|
||||
BOOL usingGzipData =
|
||||
gzippedData != nil && gzippedData.length < requestProtoData.length;
|
||||
NSData *dataToSend = usingGzipData ? gzippedData : requestProtoData;
|
||||
NSURLRequest *request = [self constructRequestWithURL:self.uploadURL
|
||||
forTarget:target
|
||||
data:dataToSend];
|
||||
GDTCORLogDebug(@"CTT: request containing %lu events for batch: %@ for target: "
|
||||
@"%ld created: %@",
|
||||
(unsigned long)batch.events.count, batch.batchID, (long)target,
|
||||
request);
|
||||
return request;
|
||||
}]
|
||||
.thenOn(self.uploaderQueue,
|
||||
^FBLPromise<GDTCCTURLSessionDataResponse *> *(NSURLRequest *request) {
|
||||
// 2. Send URL request.
|
||||
NSURLSession *session = [self uploaderSessionCreateIfNeeded];
|
||||
return [FBLPromise wrapObjectOrErrorCompletion:^(
|
||||
FBLPromiseObjectOrErrorCompletion _Nonnull handler) {
|
||||
[[session dataTaskWithRequest:request
|
||||
completionHandler:^(NSData *_Nullable data,
|
||||
NSURLResponse *_Nullable response,
|
||||
NSError *_Nullable error) {
|
||||
if (error) {
|
||||
handler(nil, error);
|
||||
} else {
|
||||
handler([[GDTCCTURLSessionDataResponse alloc]
|
||||
initWithResponse:(NSHTTPURLResponse *)response
|
||||
HTTPBody:data],
|
||||
nil);
|
||||
}
|
||||
}] resume];
|
||||
}];
|
||||
})
|
||||
.thenOn(self.uploaderQueue,
|
||||
^GDTCCTURLSessionDataResponse *(GDTCCTURLSessionDataResponse *response) {
|
||||
// Invalidate session to release the delegate (which is `self`) to break the retain
|
||||
// cycle.
|
||||
[self.uploaderSession finishTasksAndInvalidate];
|
||||
return response;
|
||||
})
|
||||
.recoverOn(self.uploaderQueue, ^id(NSError *error) {
|
||||
// Invalidate session to release the delegate (which is `self`) to break the retain cycle.
|
||||
[self.uploaderSession finishTasksAndInvalidate];
|
||||
// Re-throw the error.
|
||||
return error;
|
||||
});
|
||||
}
|
||||
|
||||
/** Parses server response and update next upload time for the specified target based on it. */
|
||||
- (void)updateNextUploadTimeWithResponse:(GDTCCTURLSessionDataResponse *)response
|
||||
forTarget:(GDTCORTarget)target {
|
||||
GDTCORClock *futureUploadTime;
|
||||
if (response.HTTPBody) {
|
||||
NSError *decodingError;
|
||||
gdt_cct_LogResponse logResponse = GDTCCTDecodeLogResponse(response.HTTPBody, &decodingError);
|
||||
if (!decodingError && logResponse.has_next_request_wait_millis) {
|
||||
GDTCORLogDebug(@"CCT: The backend responded asking to not upload for %lld millis from now.",
|
||||
logResponse.next_request_wait_millis);
|
||||
futureUploadTime =
|
||||
[GDTCORClock clockSnapshotInTheFuture:logResponse.next_request_wait_millis];
|
||||
} else if (decodingError) {
|
||||
GDTCORLogDebug(@"There was a response decoding error: %@", decodingError);
|
||||
}
|
||||
pb_release(gdt_cct_LogResponse_fields, &logResponse);
|
||||
}
|
||||
|
||||
// If no futureUploadTime was parsed from the response body, then check
|
||||
// [Retry-After](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Retry-After) header.
|
||||
if (!futureUploadTime) {
|
||||
NSString *retryAfterHeader = response.HTTPResponse.allHeaderFields[@"Retry-After"];
|
||||
if (retryAfterHeader.length > 0) {
|
||||
NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
|
||||
formatter.numberStyle = NSNumberFormatterDecimalStyle;
|
||||
NSNumber *retryAfterSeconds = [formatter numberFromString:retryAfterHeader];
|
||||
if (retryAfterSeconds != nil) {
|
||||
uint64_t retryAfterMillis = retryAfterSeconds.unsignedIntegerValue * 1000u;
|
||||
futureUploadTime = [GDTCORClock clockSnapshotInTheFuture:retryAfterMillis];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!futureUploadTime) {
|
||||
GDTCORLogDebug(@"%@", @"CCT: The backend response failed to parse, so the next request "
|
||||
@"won't occur until 15 minutes from now");
|
||||
// 15 minutes from now.
|
||||
futureUploadTime = [GDTCORClock clockSnapshotInTheFuture:15 * 60 * 1000];
|
||||
}
|
||||
|
||||
[self.metadataProvider setNextUploadTime:futureUploadTime forTarget:target];
|
||||
}
|
||||
|
||||
#pragma mark - Private helper methods
|
||||
|
||||
/** @return A resolved promise if is ready and a rejected promise if not. */
|
||||
- (FBLPromise<NSNull *> *)isReadyToUploadTarget:(GDTCORTarget)target
|
||||
conditions:(GDTCORUploadConditions)conditions {
|
||||
FBLPromise<NSNull *> *promise = [FBLPromise pendingPromise];
|
||||
if ([self readyToUploadTarget:target conditions:conditions]) {
|
||||
[promise fulfill:[NSNull null]];
|
||||
} else {
|
||||
NSString *reason =
|
||||
[NSString stringWithFormat:@"Target %ld is not ready to upload with condition: %ld",
|
||||
(long)target, (long)conditions];
|
||||
[promise reject:[self genericRejectedPromiseErrorWithReason:reason]];
|
||||
}
|
||||
return promise;
|
||||
}
|
||||
|
||||
// TODO: Move to a separate class/extension/file when needed in other files.
|
||||
/** Returns an error object with the specified failure reason. */
|
||||
- (NSError *)genericRejectedPromiseErrorWithReason:(NSString *)reason {
|
||||
return [NSError errorWithDomain:@"GDTCCTUploader"
|
||||
code:-1
|
||||
userInfo:@{NSLocalizedFailureReasonErrorKey : reason}];
|
||||
}
|
||||
|
||||
/** Returns if the specified target is ready to be uploaded based on the specified conditions. */
|
||||
- (BOOL)readyToUploadTarget:(GDTCORTarget)target conditions:(GDTCORUploadConditions)conditions {
|
||||
// Not ready to upload with no network connection.
|
||||
// TODO: Reconsider using reachability to prevent an upload attempt.
|
||||
// See https://developer.apple.com/videos/play/wwdc2019/712/ (49:40) for more details.
|
||||
if (conditions & GDTCORUploadConditionNoNetwork) {
|
||||
GDTCORLogDebug(@"%@", @"CCT: Not ready to upload without a network connection.");
|
||||
return NO;
|
||||
}
|
||||
|
||||
// Upload events with no additional conditions if high priority.
|
||||
if ((conditions & GDTCORUploadConditionHighPriority) == GDTCORUploadConditionHighPriority) {
|
||||
GDTCORLogDebug(@"%@", @"CCT: a high priority event is allowing an upload");
|
||||
return YES;
|
||||
}
|
||||
|
||||
// Check next upload time for the target.
|
||||
BOOL isAfterNextUploadTime = YES;
|
||||
GDTCORClock *nextUploadTime = [self.metadataProvider nextUploadTimeForTarget:target];
|
||||
if (nextUploadTime) {
|
||||
isAfterNextUploadTime = [[GDTCORClock snapshot] isAfter:nextUploadTime];
|
||||
}
|
||||
|
||||
if (isAfterNextUploadTime) {
|
||||
GDTCORLogDebug(@"CCT: can upload to target %ld because the request wait time has transpired",
|
||||
(long)target);
|
||||
} else {
|
||||
GDTCORLogDebug(@"CCT: can't upload to target %ld because the backend asked to wait",
|
||||
(long)target);
|
||||
}
|
||||
|
||||
return isAfterNextUploadTime;
|
||||
}
|
||||
|
||||
/** Constructs data given an upload package.
|
||||
*
|
||||
* @param events The events used to construct the request proto bytes.
|
||||
* @return Proto bytes representing a gdt_cct_LogRequest object.
|
||||
*/
|
||||
- (nonnull NSData *)constructRequestProtoWithEvents:(NSSet<GDTCOREvent *> *)events {
|
||||
// Segment the log events by log type.
|
||||
NSMutableDictionary<NSString *, NSMutableSet<GDTCOREvent *> *> *logMappingIDToLogSet =
|
||||
[[NSMutableDictionary alloc] init];
|
||||
[events enumerateObjectsUsingBlock:^(GDTCOREvent *_Nonnull event, BOOL *_Nonnull stop) {
|
||||
NSMutableSet *logSet = logMappingIDToLogSet[event.mappingID];
|
||||
logSet = logSet ? logSet : [[NSMutableSet alloc] init];
|
||||
[logSet addObject:event];
|
||||
logMappingIDToLogSet[event.mappingID] = logSet;
|
||||
}];
|
||||
|
||||
gdt_cct_BatchedLogRequest batchedLogRequest =
|
||||
GDTCCTConstructBatchedLogRequest(logMappingIDToLogSet);
|
||||
|
||||
NSData *data = GDTCCTEncodeBatchedLogRequest(&batchedLogRequest);
|
||||
pb_release(gdt_cct_BatchedLogRequest_fields, &batchedLogRequest);
|
||||
return data ? data : [[NSData alloc] init];
|
||||
}
|
||||
|
||||
/** Constructs a request to the given URL and target with the specified request body data.
|
||||
*
|
||||
* @param target The target backend to send the request to.
|
||||
* @param data The request body data.
|
||||
* @return A new NSURLRequest ready to be sent to FLL.
|
||||
*/
|
||||
- (nullable NSURLRequest *)constructRequestWithURL:(NSURL *)URL
|
||||
forTarget:(GDTCORTarget)target
|
||||
data:(NSData *)data {
|
||||
if (data == nil || data.length == 0) {
|
||||
GDTCORLogDebug(@"There was no data to construct a request for target %ld.", (long)target);
|
||||
return nil;
|
||||
}
|
||||
|
||||
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:URL];
|
||||
NSString *targetString;
|
||||
switch (target) {
|
||||
case kGDTCORTargetCCT:
|
||||
targetString = @"cct";
|
||||
break;
|
||||
|
||||
case kGDTCORTargetFLL:
|
||||
targetString = @"fll";
|
||||
break;
|
||||
|
||||
case kGDTCORTargetCSH:
|
||||
targetString = @"csh";
|
||||
break;
|
||||
case kGDTCORTargetINT:
|
||||
targetString = @"int";
|
||||
break;
|
||||
|
||||
default:
|
||||
targetString = @"unknown";
|
||||
break;
|
||||
}
|
||||
NSString *userAgent =
|
||||
[NSString stringWithFormat:@"datatransport/%@ %@support/%@ apple/", kGDTCORVersion,
|
||||
targetString, kGDTCCTSupportSDKVersion];
|
||||
|
||||
[request setValue:[self.metadataProvider APIKeyForTarget:target]
|
||||
forHTTPHeaderField:@"X-Goog-Api-Key"];
|
||||
|
||||
if ([GDTCCTCompressionHelper isGzipped:data]) {
|
||||
[request setValue:@"gzip" forHTTPHeaderField:@"Content-Encoding"];
|
||||
}
|
||||
[request setValue:@"application/x-protobuf" forHTTPHeaderField:@"Content-Type"];
|
||||
[request setValue:@"gzip" forHTTPHeaderField:@"Accept-Encoding"];
|
||||
[request setValue:userAgent forHTTPHeaderField:@"User-Agent"];
|
||||
request.HTTPMethod = @"POST";
|
||||
[request setHTTPBody:data];
|
||||
return request;
|
||||
}
|
||||
|
||||
/** Creates and returns a storage event selector for the specified target and conditions. */
|
||||
- (GDTCORStorageEventSelector *)eventSelectorTarget:(GDTCORTarget)target
|
||||
withConditions:(GDTCORUploadConditions)conditions {
|
||||
if ((conditions & GDTCORUploadConditionHighPriority) == GDTCORUploadConditionHighPriority) {
|
||||
return [GDTCORStorageEventSelector eventSelectorForTarget:target];
|
||||
}
|
||||
NSMutableSet<NSNumber *> *qosTiers = [[NSMutableSet alloc] init];
|
||||
if (conditions & GDTCORUploadConditionWifiData) {
|
||||
[qosTiers addObjectsFromArray:@[
|
||||
@(GDTCOREventQoSFast), @(GDTCOREventQoSWifiOnly), @(GDTCOREventQosDefault),
|
||||
@(GDTCOREventQoSTelemetry), @(GDTCOREventQoSUnknown)
|
||||
]];
|
||||
}
|
||||
if (conditions & GDTCORUploadConditionMobileData) {
|
||||
[qosTiers addObjectsFromArray:@[ @(GDTCOREventQoSFast), @(GDTCOREventQosDefault) ]];
|
||||
}
|
||||
|
||||
return [[GDTCORStorageEventSelector alloc] initWithTarget:target
|
||||
eventIDs:nil
|
||||
mappingIDs:nil
|
||||
qosTiers:qosTiers];
|
||||
}
|
||||
|
||||
- (FBLPromise<GDTCORUploadBatch *> *)batchByAddingMetricsEventToBatch:(GDTCORUploadBatch *)batch
|
||||
forTarget:(GDTCORTarget)target {
|
||||
return [self.metricsController getAndResetMetrics]
|
||||
.thenOn(self.uploaderQueue,
|
||||
^GDTCORUploadBatch *(GDTCORMetrics *metrics) {
|
||||
// Save the metrics so they can be re-stored if upload fails.
|
||||
[self setCurrentMetrics:metrics];
|
||||
|
||||
GDTCOREvent *metricsEvent = [GDTCOREvent eventWithMetrics:metrics forTarget:target];
|
||||
GDTCORUploadBatch *batchWithMetricEvent = [[GDTCORUploadBatch alloc]
|
||||
initWithBatchID:batch.batchID
|
||||
events:[batch.events setByAddingObject:metricsEvent]];
|
||||
|
||||
return batchWithMetricEvent;
|
||||
})
|
||||
.recoverOn(self.uploaderQueue, ^GDTCORUploadBatch *(NSError *error) {
|
||||
// Return given batch if an error occurs (i.e. no metrics were fetched).
|
||||
return batch;
|
||||
});
|
||||
}
|
||||
|
||||
#pragma mark - NSURLSessionDelegate
|
||||
|
||||
- (void)URLSession:(NSURLSession *)session
|
||||
task:(NSURLSessionTask *)task
|
||||
willPerformHTTPRedirection:(NSHTTPURLResponse *)response
|
||||
newRequest:(NSURLRequest *)request
|
||||
completionHandler:(void (^)(NSURLRequest *_Nullable))completionHandler {
|
||||
if (!completionHandler) {
|
||||
return;
|
||||
}
|
||||
if (response.statusCode == 302 || response.statusCode == 301) {
|
||||
NSURLRequest *newRequest = [self constructRequestWithURL:request.URL
|
||||
forTarget:kGDTCORTargetCCT
|
||||
data:task.originalRequest.HTTPBody];
|
||||
completionHandler(newRequest);
|
||||
} else {
|
||||
completionHandler(request);
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - NSOperation methods
|
||||
|
||||
@synthesize executing = _executing;
|
||||
@synthesize finished = _finished;
|
||||
|
||||
- (BOOL)isFinished {
|
||||
@synchronized(self) {
|
||||
return _finished;
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)isExecuting {
|
||||
@synchronized(self) {
|
||||
return _executing;
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)isAsynchronous {
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (void)startOperation {
|
||||
@synchronized(self) {
|
||||
[self willChangeValueForKey:@"isExecuting"];
|
||||
[self willChangeValueForKey:@"isFinished"];
|
||||
self->_executing = YES;
|
||||
self->_finished = NO;
|
||||
[self didChangeValueForKey:@"isExecuting"];
|
||||
[self didChangeValueForKey:@"isFinished"];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)finishOperation {
|
||||
@synchronized(self) {
|
||||
[self willChangeValueForKey:@"isExecuting"];
|
||||
[self willChangeValueForKey:@"isFinished"];
|
||||
self->_executing = NO;
|
||||
self->_finished = YES;
|
||||
[self didChangeValueForKey:@"isExecuting"];
|
||||
[self didChangeValueForKey:@"isFinished"];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)start {
|
||||
[self startOperation];
|
||||
|
||||
GDTCORLogDebug(@"Upload operation started: %@", self);
|
||||
[self uploadTarget:self.target withConditions:self.conditions];
|
||||
}
|
||||
|
||||
- (void)cancel {
|
||||
@synchronized(self) {
|
||||
[super cancel];
|
||||
|
||||
// If the operation hasn't been started we can set `isFinished = YES` straight away.
|
||||
if (!_executing) {
|
||||
_executing = NO;
|
||||
_finished = YES;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - Force Category Linking
|
||||
|
||||
extern void GDTCCTInclude_GDTCOREvent_GDTCCTSupport_Category(void);
|
||||
extern void GDTCCTInclude_GDTCOREvent_GDTMetricsSupport_Category(void);
|
||||
extern void GDTCCTInclude_GDTCORLogSourceMetrics_Internal_Category(void);
|
||||
|
||||
/// Does nothing when called, and not meant to be called.
|
||||
///
|
||||
/// This method forces the linker to include categories even if
|
||||
/// users do not include the '-ObjC' linker flag in their project.
|
||||
+ (void)noop {
|
||||
GDTCCTInclude_GDTCOREvent_GDTCCTSupport_Category();
|
||||
GDTCCTInclude_GDTCOREvent_GDTMetricsSupport_Category();
|
||||
GDTCCTInclude_GDTCORLogSourceMetrics_Internal_Category();
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
215
Pods/GoogleDataTransport/GoogleDataTransport/GDTCCTLibrary/GDTCCTUploader.m
generated
Normal file
215
Pods/GoogleDataTransport/GoogleDataTransport/GDTCCTLibrary/GDTCCTUploader.m
generated
Normal file
@ -0,0 +1,215 @@
|
||||
/*
|
||||
* Copyright 2020 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#import "GoogleDataTransport/GDTCCTLibrary/Private/GDTCCTUploader.h"
|
||||
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Internal/GDTCORPlatform.h"
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Internal/GDTCORRegistrar.h"
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORConsoleLogger.h"
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCOREndpoints.h"
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCOREvent.h"
|
||||
|
||||
#import "GoogleDataTransport/GDTCCTLibrary/Private/GDTCCTUploadOperation.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface GDTCCTUploader () <NSURLSessionDelegate, GDTCCTUploadMetadataProvider>
|
||||
|
||||
@property(nonatomic, readonly) NSOperationQueue *uploadOperationQueue;
|
||||
@property(nonatomic, readonly) dispatch_queue_t uploadQueue;
|
||||
|
||||
@property(nonatomic, readonly)
|
||||
NSMutableDictionary<NSNumber * /*GDTCORTarget*/, GDTCORClock *> *nextUploadTimeByTarget;
|
||||
|
||||
@end
|
||||
|
||||
@implementation GDTCCTUploader
|
||||
|
||||
static NSURL *_testServerURL = nil;
|
||||
|
||||
+ (void)load {
|
||||
GDTCCTUploader *uploader = [GDTCCTUploader sharedInstance];
|
||||
#if GDT_TEST
|
||||
[[GDTCORRegistrar sharedInstance] registerUploader:uploader target:kGDTCORTargetTest];
|
||||
#endif // GDT_TEST
|
||||
[[GDTCORRegistrar sharedInstance] registerUploader:uploader target:kGDTCORTargetCCT];
|
||||
[[GDTCORRegistrar sharedInstance] registerUploader:uploader target:kGDTCORTargetFLL];
|
||||
[[GDTCORRegistrar sharedInstance] registerUploader:uploader target:kGDTCORTargetCSH];
|
||||
[[GDTCORRegistrar sharedInstance] registerUploader:uploader target:kGDTCORTargetINT];
|
||||
}
|
||||
|
||||
+ (instancetype)sharedInstance {
|
||||
static GDTCCTUploader *sharedInstance;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
sharedInstance = [[GDTCCTUploader alloc] init];
|
||||
});
|
||||
return sharedInstance;
|
||||
}
|
||||
|
||||
- (instancetype)init {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_uploadQueue = dispatch_queue_create("com.google.GDTCCTUploader", DISPATCH_QUEUE_SERIAL);
|
||||
_uploadOperationQueue = [[NSOperationQueue alloc] init];
|
||||
_uploadOperationQueue.maxConcurrentOperationCount = 1;
|
||||
_nextUploadTimeByTarget = [[NSMutableDictionary alloc] init];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)uploadTarget:(GDTCORTarget)target withConditions:(GDTCORUploadConditions)conditions {
|
||||
// Current GDTCCTUploader expected behaviour:
|
||||
// 1. Accept multiple upload request
|
||||
// 2. Verify if there are events eligible for upload and start upload for the first suitable
|
||||
// target
|
||||
// 3. Ignore other requests while an upload is in-progress.
|
||||
|
||||
// TODO: Revisit expected behaviour.
|
||||
// Potentially better option:
|
||||
// 1. Accept and enqueue all upload requests
|
||||
// 2. Notify the client of upload stages
|
||||
// 3. Allow the client cancelling upload requests as needed.
|
||||
|
||||
id<GDTCORStoragePromiseProtocol> storage = GDTCORStoragePromiseInstanceForTarget(target);
|
||||
if (storage == nil) {
|
||||
GDTCORLogError(GDTCORMCEGeneralError,
|
||||
@"Failed to upload target: %ld - could not find corresponding storage instance.",
|
||||
(long)target);
|
||||
return;
|
||||
}
|
||||
|
||||
id<GDTCORMetricsControllerProtocol> metricsController =
|
||||
GDTCORMetricsControllerInstanceForTarget(target);
|
||||
|
||||
GDTCCTUploadOperation *uploadOperation =
|
||||
[[GDTCCTUploadOperation alloc] initWithTarget:target
|
||||
conditions:conditions
|
||||
uploadURL:[[self class] serverURLForTarget:target]
|
||||
queue:self.uploadQueue
|
||||
storage:storage
|
||||
metadataProvider:self
|
||||
metricsController:metricsController];
|
||||
|
||||
GDTCORLogDebug(@"Upload operation created: %@, target: %@", uploadOperation, @(target));
|
||||
|
||||
__weak __auto_type weakSelf = self;
|
||||
__weak GDTCCTUploadOperation *weakOperation = uploadOperation;
|
||||
uploadOperation.completionBlock = ^{
|
||||
__auto_type strongSelf = weakSelf;
|
||||
GDTCCTUploadOperation *strongOperation = weakOperation;
|
||||
if (strongSelf == nil || strongOperation == nil) {
|
||||
GDTCORLogDebug(@"Internal inconsistency: GDTCCTUploader was deallocated during upload.", nil);
|
||||
return;
|
||||
}
|
||||
|
||||
GDTCORLogDebug(@"Upload operation finished: %@, uploadAttempted: %@", strongOperation,
|
||||
@(strongOperation.uploadAttempted));
|
||||
|
||||
if (strongOperation.uploadAttempted) {
|
||||
// Ignore all upload requests received when the upload was in progress.
|
||||
[strongSelf.uploadOperationQueue cancelAllOperations];
|
||||
}
|
||||
};
|
||||
|
||||
[self.uploadOperationQueue addOperation:uploadOperation];
|
||||
GDTCORLogDebug(@"Upload operation scheduled: %@, operation count: %@", uploadOperation,
|
||||
@(self.uploadOperationQueue.operationCount));
|
||||
}
|
||||
|
||||
#pragma mark - URLs
|
||||
|
||||
+ (void)setTestServerURL:(NSURL *_Nullable)serverURL {
|
||||
_testServerURL = serverURL;
|
||||
}
|
||||
|
||||
+ (NSURL *_Nullable)testServerURL {
|
||||
return _testServerURL;
|
||||
}
|
||||
|
||||
+ (nullable NSURL *)serverURLForTarget:(GDTCORTarget)target {
|
||||
#if GDT_TEST
|
||||
if (_testServerURL) {
|
||||
return _testServerURL;
|
||||
}
|
||||
#endif // GDT_TEST
|
||||
|
||||
return [GDTCOREndpoints uploadURLForTarget:target];
|
||||
}
|
||||
|
||||
- (NSString *)FLLAndCSHAndINTAPIKey {
|
||||
static NSString *defaultServerKey;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
// These strings should be interleaved to construct the real key.
|
||||
const char *p1 = "AzSBG0honD6A-PxV5nBc";
|
||||
const char *p2 = "Iay44Iwtu2vV0AOrz1C";
|
||||
const char defaultKey[40] = {p1[0], p2[0], p1[1], p2[1], p1[2], p2[2], p1[3], p2[3],
|
||||
p1[4], p2[4], p1[5], p2[5], p1[6], p2[6], p1[7], p2[7],
|
||||
p1[8], p2[8], p1[9], p2[9], p1[10], p2[10], p1[11], p2[11],
|
||||
p1[12], p2[12], p1[13], p2[13], p1[14], p2[14], p1[15], p2[15],
|
||||
p1[16], p2[16], p1[17], p2[17], p1[18], p2[18], p1[19], '\0'};
|
||||
defaultServerKey = [NSString stringWithUTF8String:defaultKey];
|
||||
});
|
||||
return defaultServerKey;
|
||||
}
|
||||
|
||||
#pragma mark - GDTCCTUploadMetadataProvider
|
||||
|
||||
- (nullable GDTCORClock *)nextUploadTimeForTarget:(GDTCORTarget)target {
|
||||
@synchronized(self.nextUploadTimeByTarget) {
|
||||
return self.nextUploadTimeByTarget[@(target)];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setNextUploadTime:(nullable GDTCORClock *)time forTarget:(GDTCORTarget)target {
|
||||
@synchronized(self.nextUploadTimeByTarget) {
|
||||
self.nextUploadTimeByTarget[@(target)] = time;
|
||||
}
|
||||
}
|
||||
|
||||
- (nullable NSString *)APIKeyForTarget:(GDTCORTarget)target {
|
||||
if (target == kGDTCORTargetFLL || target == kGDTCORTargetCSH) {
|
||||
return [self FLLAndCSHAndINTAPIKey];
|
||||
}
|
||||
|
||||
if (target == kGDTCORTargetINT) {
|
||||
return [self FLLAndCSHAndINTAPIKey];
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
#if GDT_TEST
|
||||
- (BOOL)waitForUploadFinishedWithTimeout:(NSTimeInterval)timeout {
|
||||
NSDate *expirationDate = [NSDate dateWithTimeIntervalSinceNow:timeout];
|
||||
while ([expirationDate compare:[NSDate date]] == NSOrderedDescending) {
|
||||
if (self.uploadOperationQueue.operationCount == 0) {
|
||||
return YES;
|
||||
} else {
|
||||
[[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
|
||||
}
|
||||
}
|
||||
|
||||
GDTCORLogDebug(@"Uploader wait for finish timeout exceeded. Operations still in queue: %@",
|
||||
self.uploadOperationQueue.operations);
|
||||
return NO;
|
||||
}
|
||||
#endif // GDT_TEST
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
244
Pods/GoogleDataTransport/GoogleDataTransport/GDTCCTLibrary/GDTCOREvent+GDTCCTSupport.m
generated
Normal file
244
Pods/GoogleDataTransport/GoogleDataTransport/GDTCCTLibrary/GDTCOREvent+GDTCCTSupport.m
generated
Normal file
@ -0,0 +1,244 @@
|
||||
/*
|
||||
* Copyright 2020 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#import "GoogleDataTransport/GDTCCTLibrary/Public/GDTCOREvent+GDTCCTSupport.h"
|
||||
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORConsoleLogger.h"
|
||||
|
||||
NSString *const GDTCCTNeedsNetworkConnectionInfo = @"needs_network_connection_info";
|
||||
|
||||
NSString *const GDTCCTNetworkConnectionInfo = @"network_connection_info";
|
||||
|
||||
NSString *const GDTCCTEventCodeInfo = @"event_code_info";
|
||||
|
||||
@implementation GDTCOREvent (GDTCCTSupport)
|
||||
|
||||
- (void)setNeedsNetworkConnectionInfoPopulated:(BOOL)needsNetworkConnectionInfoPopulated {
|
||||
if (!needsNetworkConnectionInfoPopulated) {
|
||||
if (!self.customBytes) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Make sure we don't destroy the eventCode data, if any is present.
|
||||
@try {
|
||||
NSError *error;
|
||||
NSMutableDictionary *bytesDict =
|
||||
[[NSJSONSerialization JSONObjectWithData:self.customBytes options:0
|
||||
error:&error] mutableCopy];
|
||||
if (error) {
|
||||
GDTCORLogDebug(@"Error when setting an event's event_code: %@", error);
|
||||
return;
|
||||
}
|
||||
NSNumber *eventCode = bytesDict[GDTCCTEventCodeInfo];
|
||||
if (eventCode != nil) {
|
||||
self.customBytes =
|
||||
[NSJSONSerialization dataWithJSONObject:@{GDTCCTEventCodeInfo : eventCode}
|
||||
options:0
|
||||
error:&error];
|
||||
}
|
||||
} @catch (NSException *exception) {
|
||||
GDTCORLogDebug(@"Error when setting the event for needs_network_connection_info: %@",
|
||||
exception);
|
||||
}
|
||||
} else {
|
||||
@try {
|
||||
NSError *error;
|
||||
NSMutableDictionary *bytesDict;
|
||||
if (self.customBytes) {
|
||||
bytesDict = [[NSJSONSerialization JSONObjectWithData:self.customBytes
|
||||
options:0
|
||||
error:&error] mutableCopy];
|
||||
if (error) {
|
||||
GDTCORLogDebug(@"Error when setting an even'ts event_code: %@", error);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
bytesDict = [[NSMutableDictionary alloc] init];
|
||||
}
|
||||
[bytesDict setObject:@YES forKey:GDTCCTNeedsNetworkConnectionInfo];
|
||||
self.customBytes = [NSJSONSerialization dataWithJSONObject:bytesDict options:0 error:&error];
|
||||
} @catch (NSException *exception) {
|
||||
GDTCORLogDebug(@"Error when setting the event for needs_network_connection_info: %@",
|
||||
exception);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)needsNetworkConnectionInfoPopulated {
|
||||
if (self.customBytes) {
|
||||
@try {
|
||||
NSError *error;
|
||||
NSDictionary *bytesDict = [NSJSONSerialization JSONObjectWithData:self.customBytes
|
||||
options:0
|
||||
error:&error];
|
||||
return bytesDict && !error && [bytesDict[GDTCCTNeedsNetworkConnectionInfo] boolValue];
|
||||
} @catch (NSException *exception) {
|
||||
GDTCORLogDebug(@"Error when checking the event for needs_network_connection_info: %@",
|
||||
exception);
|
||||
}
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (void)setNetworkConnectionInfoData:(NSData *)networkConnectionInfoData {
|
||||
@try {
|
||||
NSError *error;
|
||||
NSString *dataString = [networkConnectionInfoData base64EncodedStringWithOptions:0];
|
||||
if (dataString != nil) {
|
||||
NSMutableDictionary *bytesDict;
|
||||
if (self.customBytes) {
|
||||
bytesDict = [[NSJSONSerialization JSONObjectWithData:self.customBytes
|
||||
options:0
|
||||
error:&error] mutableCopy];
|
||||
if (error) {
|
||||
GDTCORLogDebug(@"Error when setting an even'ts event_code: %@", error);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
bytesDict = [[NSMutableDictionary alloc] init];
|
||||
}
|
||||
[bytesDict setObject:dataString forKey:GDTCCTNetworkConnectionInfo];
|
||||
self.customBytes = [NSJSONSerialization dataWithJSONObject:bytesDict options:0 error:&error];
|
||||
if (error) {
|
||||
self.customBytes = nil;
|
||||
GDTCORLogDebug(@"Error when setting an event's network_connection_info: %@", error);
|
||||
}
|
||||
}
|
||||
} @catch (NSException *exception) {
|
||||
GDTCORLogDebug(@"Error when setting an event's network_connection_info: %@", exception);
|
||||
}
|
||||
}
|
||||
|
||||
- (nullable NSData *)networkConnectionInfoData {
|
||||
if (self.customBytes) {
|
||||
@try {
|
||||
NSError *error;
|
||||
NSDictionary *bytesDict = [NSJSONSerialization JSONObjectWithData:self.customBytes
|
||||
options:0
|
||||
error:&error];
|
||||
NSString *base64Data = bytesDict[GDTCCTNetworkConnectionInfo];
|
||||
if (base64Data == nil) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
NSData *networkConnectionInfoData = [[NSData alloc] initWithBase64EncodedString:base64Data
|
||||
options:0];
|
||||
if (error) {
|
||||
GDTCORLogDebug(@"Error when getting an event's network_connection_info: %@", error);
|
||||
return nil;
|
||||
} else {
|
||||
return networkConnectionInfoData;
|
||||
}
|
||||
} @catch (NSException *exception) {
|
||||
GDTCORLogDebug(@"Error when getting an event's network_connection_info: %@", exception);
|
||||
}
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (NSNumber *)eventCode {
|
||||
if (self.customBytes) {
|
||||
@try {
|
||||
NSError *error;
|
||||
NSDictionary *bytesDict = [NSJSONSerialization JSONObjectWithData:self.customBytes
|
||||
options:0
|
||||
error:&error];
|
||||
NSString *eventCodeString = bytesDict[GDTCCTEventCodeInfo];
|
||||
|
||||
if (!eventCodeString) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
|
||||
formatter.numberStyle = NSNumberFormatterDecimalStyle;
|
||||
NSNumber *eventCode = [formatter numberFromString:eventCodeString];
|
||||
|
||||
if (error) {
|
||||
GDTCORLogDebug(@"Error when getting an event's network_connection_info: %@", error);
|
||||
return nil;
|
||||
} else {
|
||||
return eventCode;
|
||||
}
|
||||
} @catch (NSException *exception) {
|
||||
GDTCORLogDebug(@"Error when getting an event's event_code: %@", exception);
|
||||
}
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (void)setEventCode:(NSNumber *)eventCode {
|
||||
if (eventCode == nil) {
|
||||
if (!self.customBytes) {
|
||||
return;
|
||||
}
|
||||
|
||||
NSError *error;
|
||||
NSMutableDictionary *bytesDict = [[NSJSONSerialization JSONObjectWithData:self.customBytes
|
||||
options:0
|
||||
error:&error] mutableCopy];
|
||||
if (error) {
|
||||
GDTCORLogDebug(@"Error when setting an event's event_code: %@", error);
|
||||
return;
|
||||
}
|
||||
|
||||
[bytesDict removeObjectForKey:GDTCCTEventCodeInfo];
|
||||
self.customBytes = [NSJSONSerialization dataWithJSONObject:bytesDict options:0 error:&error];
|
||||
if (error) {
|
||||
self.customBytes = nil;
|
||||
GDTCORLogDebug(@"Error when setting an event's event_code: %@", error);
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@try {
|
||||
NSMutableDictionary *bytesDict;
|
||||
NSError *error;
|
||||
if (self.customBytes) {
|
||||
bytesDict = [[NSJSONSerialization JSONObjectWithData:self.customBytes options:0
|
||||
error:&error] mutableCopy];
|
||||
if (error) {
|
||||
GDTCORLogDebug(@"Error when setting an event's event_code: %@", error);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
bytesDict = [[NSMutableDictionary alloc] init];
|
||||
}
|
||||
|
||||
NSString *eventCodeString = [eventCode stringValue];
|
||||
if (eventCodeString == nil) {
|
||||
return;
|
||||
}
|
||||
|
||||
[bytesDict setObject:eventCodeString forKey:GDTCCTEventCodeInfo];
|
||||
|
||||
self.customBytes = [NSJSONSerialization dataWithJSONObject:bytesDict options:0 error:&error];
|
||||
if (error) {
|
||||
self.customBytes = nil;
|
||||
GDTCORLogDebug(@"Error when setting an event's network_connection_info: %@", error);
|
||||
return;
|
||||
}
|
||||
|
||||
} @catch (NSException *exception) {
|
||||
GDTCORLogDebug(@"Error when getting an event's network_connection_info: %@", exception);
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
/// Stub used to force the linker to include the categories in this file.
|
||||
void GDTCCTInclude_GDTCOREvent_GDTCCTSupport_Category(void) {
|
||||
}
|
||||
37
Pods/GoogleDataTransport/GoogleDataTransport/GDTCCTLibrary/GDTCOREvent+GDTMetricsSupport.m
generated
Normal file
37
Pods/GoogleDataTransport/GoogleDataTransport/GDTCCTLibrary/GDTCOREvent+GDTMetricsSupport.m
generated
Normal file
@ -0,0 +1,37 @@
|
||||
// Copyright 2022 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#import "GoogleDataTransport/GDTCCTLibrary/Private/GDTCOREvent+GDTMetricsSupport.h"
|
||||
|
||||
#import "GoogleDataTransport/GDTCCTLibrary/Private/GDTCORMetrics+GDTCCTSupport.h"
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Private/GDTCORMetrics.h"
|
||||
|
||||
/// The mapping ID that represents the `LogSource` for GDT metrics.
|
||||
static NSString *const kMetricEventMappingID = @"1710";
|
||||
|
||||
@implementation GDTCOREvent (GDTMetricsSupport)
|
||||
|
||||
+ (GDTCOREvent *)eventWithMetrics:(GDTCORMetrics *)metrics forTarget:(GDTCORTarget)target {
|
||||
GDTCOREvent *metricsEvent = [[GDTCOREvent alloc] initWithMappingID:kMetricEventMappingID
|
||||
target:target];
|
||||
metricsEvent.dataObject = metrics;
|
||||
|
||||
return metricsEvent;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
/// Stub used to force the linker to include the categories in this file.
|
||||
void GDTCCTInclude_GDTCOREvent_GDTMetricsSupport_Category(void) {
|
||||
}
|
||||
211
Pods/GoogleDataTransport/GoogleDataTransport/GDTCCTLibrary/GDTCORMetrics+GDTCCTSupport.m
generated
Normal file
211
Pods/GoogleDataTransport/GoogleDataTransport/GDTCCTLibrary/GDTCORMetrics+GDTCCTSupport.m
generated
Normal file
@ -0,0 +1,211 @@
|
||||
// Copyright 2022 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#import "GoogleDataTransport/GDTCCTLibrary/Private/GDTCORMetrics+GDTCCTSupport.h"
|
||||
|
||||
#import <nanopb/pb.h>
|
||||
#import <nanopb/pb_decode.h>
|
||||
#import <nanopb/pb_encode.h>
|
||||
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORConsoleLogger.h"
|
||||
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Internal/GDTCOREventDropReason.h"
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Internal/GDTCORStorageSizeBytes.h"
|
||||
|
||||
#import "GoogleDataTransport/GDTCCTLibrary/Private/GDTCCTNanopbHelpers.h"
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Private/GDTCORLogSourceMetrics.h"
|
||||
|
||||
#import "GoogleDataTransport/GDTCCTLibrary/Protogen/nanopb/client_metrics.nanopb.h"
|
||||
|
||||
typedef NSDictionary<NSNumber *, NSNumber *> GDTCORDroppedEventCounter;
|
||||
|
||||
@interface GDTCORLogSourceMetrics (Internal)
|
||||
|
||||
/// A dictionary of log sources that map to counters that reflect the number of events dropped for a
|
||||
/// given set of reasons (``GDTCOREventDropReason``).
|
||||
@property(nonatomic, readonly)
|
||||
NSDictionary<NSString *, GDTCORDroppedEventCounter *> *droppedEventCounterByLogSource;
|
||||
|
||||
@end
|
||||
|
||||
@implementation GDTCORMetrics (GDTCCTSupport)
|
||||
|
||||
- (NSData *)transportBytes {
|
||||
// Create and populate proto.
|
||||
gdt_client_metrics_ClientMetrics clientMetricsProto =
|
||||
gdt_client_metrics_ClientMetrics_init_default;
|
||||
|
||||
clientMetricsProto.window =
|
||||
GDTCCTConstructTimeWindow(self.collectionStartDate, self.collectionEndDate);
|
||||
|
||||
clientMetricsProto.log_source_metrics = GDTCCTConstructLogSourceMetrics(self.logSourceMetrics);
|
||||
clientMetricsProto.log_source_metrics_count =
|
||||
GDTCCTGetLogSourceMetricsCount(self.logSourceMetrics);
|
||||
|
||||
clientMetricsProto.global_metrics =
|
||||
GDTCCTConstructGlobalMetrics(self.currentCacheSize, self.maxCacheSize);
|
||||
|
||||
clientMetricsProto.app_namespace = GDTCCTEncodeString(self.bundleID);
|
||||
|
||||
// Encode proto into a data buffer.
|
||||
pb_ostream_t sizeStream = PB_OSTREAM_SIZING;
|
||||
|
||||
// - Encode 1 time to determine the expected size of the buffer.
|
||||
if (!pb_encode(&sizeStream, gdt_client_metrics_ClientMetrics_fields, &clientMetricsProto)) {
|
||||
GDTCORLogError(GDTCORMCETransportBytesError, @"Error in nanopb encoding for size: %s",
|
||||
PB_GET_ERROR(&sizeStream));
|
||||
}
|
||||
|
||||
// - Encode a 2nd time to actually copy the proto's bytes into the buffer.
|
||||
size_t bufferSize = sizeStream.bytes_written;
|
||||
CFMutableDataRef dataRef = CFDataCreateMutable(CFAllocatorGetDefault(), bufferSize);
|
||||
CFDataSetLength(dataRef, bufferSize);
|
||||
pb_ostream_t ostream = pb_ostream_from_buffer((void *)CFDataGetBytePtr(dataRef), bufferSize);
|
||||
if (!pb_encode(&ostream, gdt_client_metrics_ClientMetrics_fields, &clientMetricsProto)) {
|
||||
GDTCORLogError(GDTCORMCETransportBytesError, @"Error in nanopb encoding for size: %s",
|
||||
PB_GET_ERROR(&ostream));
|
||||
}
|
||||
CFDataSetLength(dataRef, ostream.bytes_written);
|
||||
|
||||
// Release the allocated proto.
|
||||
pb_release(gdt_client_metrics_ClientMetrics_fields, &clientMetricsProto);
|
||||
|
||||
return CFBridgingRelease(dataRef);
|
||||
}
|
||||
|
||||
/// Constructs and returns a ``gdt_client_metrics_LogSourceMetrics`` from the given log source
|
||||
/// metrics.
|
||||
/// @param logSourceMetrics The given log source metrics.
|
||||
gdt_client_metrics_LogSourceMetrics *GDTCCTConstructLogSourceMetrics(
|
||||
GDTCORLogSourceMetrics *logSourceMetrics) {
|
||||
// The metrics proto is a repeating field where each element represents the
|
||||
// dropped event data for a log source (mapping ID).
|
||||
NSUInteger logMetricsCount = logSourceMetrics.droppedEventCounterByLogSource.count;
|
||||
gdt_client_metrics_LogSourceMetrics *repeatedLogSourceMetrics =
|
||||
calloc(logMetricsCount, sizeof(gdt_client_metrics_LogSourceMetrics));
|
||||
|
||||
// Each log source (mapping ID) has a corresponding dropped event counter.
|
||||
// Enumerate over the dictionary of log source and, for each log source,
|
||||
// (mapping ID) create a proto representation of the number of events dropped
|
||||
// for each given reason.
|
||||
__block NSUInteger logSourceIndex = 0;
|
||||
[logSourceMetrics.droppedEventCounterByLogSource
|
||||
enumerateKeysAndObjectsUsingBlock:^(NSString *logSource,
|
||||
GDTCORDroppedEventCounter *eventCounterForLogSource,
|
||||
BOOL *__unused _) {
|
||||
// Create the log source proto for the given mapping ID. It contains a
|
||||
// repeating field to encapsulate the number of events dropped for each
|
||||
// given drop reason.
|
||||
__block gdt_client_metrics_LogSourceMetrics logSourceMetrics =
|
||||
gdt_client_metrics_LogSourceMetrics_init_zero;
|
||||
logSourceMetrics.log_source = GDTCCTEncodeString(logSource);
|
||||
logSourceMetrics.log_event_dropped_count = (pb_size_t)eventCounterForLogSource.count;
|
||||
logSourceMetrics.log_event_dropped =
|
||||
calloc(eventCounterForLogSource.count, sizeof(gdt_client_metrics_LogEventDropped));
|
||||
|
||||
// Each dropped event counter counts the number of events dropped for
|
||||
// each drop reason. Enumerate over all of these counters to populate
|
||||
// the log source proto's repeating field of event drop data.
|
||||
__block NSUInteger eventCounterIndex = 0;
|
||||
[eventCounterForLogSource
|
||||
enumerateKeysAndObjectsUsingBlock:^(NSNumber *eventDropReason,
|
||||
NSNumber *droppedEventCount, BOOL *__unused _) {
|
||||
gdt_client_metrics_LogEventDropped droppedEvents =
|
||||
gdt_client_metrics_LogEventDropped_init_zero;
|
||||
droppedEvents.events_dropped_count = droppedEventCount.integerValue;
|
||||
droppedEvents.reason =
|
||||
GDTCCTConvertEventDropReasonToProtoReason(eventDropReason.integerValue);
|
||||
|
||||
// Append the dropped events proto to the repeated field and
|
||||
// increment the index used for appending.
|
||||
logSourceMetrics.log_event_dropped[eventCounterIndex] = droppedEvents;
|
||||
eventCounterIndex += 1;
|
||||
}];
|
||||
|
||||
// Append the metrics for the given log source (mappingID) to the
|
||||
// repeated field and increment the index used for appending.
|
||||
repeatedLogSourceMetrics[logSourceIndex] = logSourceMetrics;
|
||||
logSourceIndex += 1;
|
||||
}];
|
||||
|
||||
return repeatedLogSourceMetrics;
|
||||
}
|
||||
|
||||
/// Returns the count of log sources that have event drop metrics.
|
||||
/// @param logSourceMetrics The given log source metrics.
|
||||
pb_size_t GDTCCTGetLogSourceMetricsCount(GDTCORLogSourceMetrics *logSourceMetrics) {
|
||||
return (pb_size_t)logSourceMetrics.droppedEventCounterByLogSource.count;
|
||||
}
|
||||
|
||||
/// Constructs and returns a ``gdt_client_metrics_TimeWindow`` proto from the given parameters.
|
||||
/// @param collectionStartDate The start of the time window.
|
||||
/// @param collectionEndDate The end of the time window.
|
||||
gdt_client_metrics_TimeWindow GDTCCTConstructTimeWindow(NSDate *collectionStartDate,
|
||||
NSDate *collectionEndDate) {
|
||||
gdt_client_metrics_TimeWindow timeWindow = gdt_client_metrics_TimeWindow_init_zero;
|
||||
// `- [NSDate timeIntervalSince1970]` returns a time interval in seconds so
|
||||
// multiply by 1000 to convert to milliseconds.
|
||||
timeWindow.start_ms = (int64_t)collectionStartDate.timeIntervalSince1970 * 1000;
|
||||
timeWindow.end_ms = (int64_t)collectionEndDate.timeIntervalSince1970 * 1000;
|
||||
return timeWindow;
|
||||
}
|
||||
|
||||
/// Constructs and returns a ``gdt_client_metrics_GlobalMetrics`` proto from the given parameters.
|
||||
/// @param currentCacheSize The current cache size.
|
||||
/// @param maxCacheSize The max cache size.
|
||||
gdt_client_metrics_GlobalMetrics GDTCCTConstructGlobalMetrics(uint64_t currentCacheSize,
|
||||
uint64_t maxCacheSize) {
|
||||
gdt_client_metrics_StorageMetrics storageMetrics = gdt_client_metrics_StorageMetrics_init_zero;
|
||||
storageMetrics.current_cache_size_bytes = currentCacheSize;
|
||||
storageMetrics.max_cache_size_bytes = maxCacheSize;
|
||||
|
||||
gdt_client_metrics_GlobalMetrics globalMetrics = gdt_client_metrics_GlobalMetrics_init_zero;
|
||||
globalMetrics.storage_metrics = storageMetrics;
|
||||
|
||||
return globalMetrics;
|
||||
}
|
||||
|
||||
/// Returns the corresponding ``gdt_client_metrics_LogEventDropped_Reason`` for the given
|
||||
/// ``GDTCOREventDropReason``.
|
||||
///
|
||||
/// To represent ``GDTCOREventDropReason`` in a proto, the reason must be mapped to a
|
||||
/// ``gdt_client_metrics_LogEventDropped_Reason``.
|
||||
///
|
||||
/// @param reason The ``GDTCOREventDropReason`` to represent in a proto.
|
||||
gdt_client_metrics_LogEventDropped_Reason GDTCCTConvertEventDropReasonToProtoReason(
|
||||
GDTCOREventDropReason reason) {
|
||||
switch (reason) {
|
||||
case GDTCOREventDropReasonUnknown:
|
||||
return gdt_client_metrics_LogEventDropped_Reason_REASON_UNKNOWN;
|
||||
case GDTCOREventDropReasonMessageTooOld:
|
||||
return gdt_client_metrics_LogEventDropped_Reason_MESSAGE_TOO_OLD;
|
||||
case GDTCOREventDropReasonStorageFull:
|
||||
return gdt_client_metrics_LogEventDropped_Reason_CACHE_FULL;
|
||||
case GDTCOREventDropReasonPayloadTooBig:
|
||||
return gdt_client_metrics_LogEventDropped_Reason_PAYLOAD_TOO_BIG;
|
||||
case GDTCOREventDropReasonMaxRetriesReached:
|
||||
return gdt_client_metrics_LogEventDropped_Reason_MAX_RETRIES_REACHED;
|
||||
case GDTCOREventDropReasonInvalidPayload:
|
||||
// The below typo (`PAYLOD`) is currently checked in to g3.
|
||||
return gdt_client_metrics_LogEventDropped_Reason_INVALID_PAYLOD;
|
||||
case GDTCOREventDropReasonServerError:
|
||||
return gdt_client_metrics_LogEventDropped_Reason_SERVER_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
/// Stub used to force the linker to include the categories in this file.
|
||||
void GDTCCTInclude_GDTCORLogSourceMetrics_Internal_Category(void) {
|
||||
}
|
||||
40
Pods/GoogleDataTransport/GoogleDataTransport/GDTCCTLibrary/Private/GDTCCTCompressionHelper.h
generated
Normal file
40
Pods/GoogleDataTransport/GoogleDataTransport/GDTCCTLibrary/Private/GDTCCTCompressionHelper.h
generated
Normal file
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright 2020 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/** A class with methods to help with gzipped data. */
|
||||
@interface GDTCCTCompressionHelper : NSObject
|
||||
|
||||
/** Compresses the given data and returns a new data object.
|
||||
*
|
||||
* @note Reduced version from GULNSData+zlib.m of GoogleUtilities.
|
||||
* @return Compressed data, or nil if there was an error.
|
||||
*/
|
||||
+ (nullable NSData *)gzippedData:(NSData *)data;
|
||||
|
||||
/** Returns YES if the data looks like it was gzip compressed by checking for the gzip magic number.
|
||||
*
|
||||
* @note: From https://en.wikipedia.org/wiki/Gzip, gzip's magic number is 1f 8b.
|
||||
* @return YES if the data appears gzipped, NO otherwise.
|
||||
*/
|
||||
+ (BOOL)isGzipped:(NSData *)data;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
144
Pods/GoogleDataTransport/GoogleDataTransport/GDTCCTLibrary/Private/GDTCCTNanopbHelpers.h
generated
Normal file
144
Pods/GoogleDataTransport/GoogleDataTransport/GDTCCTLibrary/Private/GDTCCTNanopbHelpers.h
generated
Normal file
@ -0,0 +1,144 @@
|
||||
/*
|
||||
* Copyright 2019 Google
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Internal/GDTCORReachability.h"
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCOREvent.h"
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORProductData.h"
|
||||
|
||||
#import "GoogleDataTransport/GDTCCTLibrary/Protogen/nanopb/cct.nanopb.h"
|
||||
#import "GoogleDataTransport/GDTCCTLibrary/Protogen/nanopb/compliance.nanopb.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
#pragma mark - General purpose encoders
|
||||
|
||||
/** Converts an NSString* to a pb_bytes_array_t*.
|
||||
*
|
||||
* @note calloc is called in this method. Ensure that pb_release is called on this or the parent.
|
||||
*
|
||||
* @param string The string to convert.
|
||||
* @return A newly allocated array of bytes representing the UTF8 encoding of the string.
|
||||
*/
|
||||
pb_bytes_array_t *GDTCCTEncodeString(NSString *string);
|
||||
|
||||
/** Converts an NSData to a pb_bytes_array_t*.
|
||||
*
|
||||
* @note calloc is called in this method. Ensure that pb_release is called on this or the parent.
|
||||
*
|
||||
* @param data The data to convert.
|
||||
* @return A newly allocated array of bytes with [data bytes] copied into it.
|
||||
*/
|
||||
pb_bytes_array_t *GDTCCTEncodeData(NSData *data);
|
||||
|
||||
#pragma mark - CCT object constructors
|
||||
|
||||
/** Encodes a batched log request.
|
||||
*
|
||||
* @note Ensure that pb_release is called on the batchedLogRequest param.
|
||||
*
|
||||
* @param batchedLogRequest A pointer to the log batch to encode to bytes.
|
||||
* @return An NSData object representing the bytes of the log request batch.
|
||||
*/
|
||||
FOUNDATION_EXPORT
|
||||
NSData *GDTCCTEncodeBatchedLogRequest(gdt_cct_BatchedLogRequest *batchedLogRequest);
|
||||
|
||||
/** Constructs a gdt_cct_BatchedLogRequest given sets of events segemented by mapping ID.
|
||||
*
|
||||
* @note calloc is called in this method. Ensure that pb_release is called on this or the parent.
|
||||
*
|
||||
* @param logMappingIDToLogSet A map of mapping IDs to sets of events to convert into a batch.
|
||||
* @return A newly created gdt_cct_BatchedLogRequest.
|
||||
*/
|
||||
FOUNDATION_EXPORT
|
||||
gdt_cct_BatchedLogRequest GDTCCTConstructBatchedLogRequest(
|
||||
NSDictionary<NSString *, NSSet<GDTCOREvent *> *> *logMappingIDToLogSet);
|
||||
|
||||
/** Constructs a log request given a log source and a set of events.
|
||||
*
|
||||
* @note calloc is called in this method. Ensure that pb_release is called on this or the parent.
|
||||
* @param logSource The CCT log source to put into the log request.
|
||||
* @param logSet The set of events to send in this log request.
|
||||
*/
|
||||
FOUNDATION_EXPORT
|
||||
gdt_cct_LogRequest GDTCCTConstructLogRequest(int32_t logSource, NSSet<GDTCOREvent *> *logSet);
|
||||
|
||||
/** Constructs a gdt_cct_LogEvent given a GDTCOREvent*.
|
||||
*
|
||||
* @param event The GDTCOREvent to convert.
|
||||
* @return The new gdt_cct_LogEvent object.
|
||||
*/
|
||||
FOUNDATION_EXPORT
|
||||
gdt_cct_LogEvent GDTCCTConstructLogEvent(GDTCOREvent *event);
|
||||
|
||||
/** Constructs a `gdt_cct_ComplianceData` given a `GDTCORProductData` instance.
|
||||
*
|
||||
* @param productData The product data to convert to compliance data.
|
||||
*/
|
||||
FOUNDATION_EXPORT
|
||||
gdt_cct_ComplianceData GDTCCTConstructComplianceData(GDTCORProductData *productData);
|
||||
|
||||
/** Constructs a gdt_cct_ClientInfo representing the client device.
|
||||
*
|
||||
* @return The new gdt_cct_ClientInfo object.
|
||||
*/
|
||||
FOUNDATION_EXPORT
|
||||
gdt_cct_ClientInfo GDTCCTConstructClientInfo(void);
|
||||
|
||||
/** Constructs a gdt_cct_IosClientInfo representing the client device.
|
||||
*
|
||||
* @return The new gdt_cct_IosClientInfo object.
|
||||
*/
|
||||
FOUNDATION_EXPORT
|
||||
gdt_cct_IosClientInfo GDTCCTConstructiOSClientInfo(void);
|
||||
|
||||
/** Constructs a gdt_cct_MacClientInfo representing the client device.
|
||||
*
|
||||
* @return The new gdt_cct_MacClientInfo object.
|
||||
*/
|
||||
FOUNDATION_EXPORT
|
||||
gdt_cct_MacClientInfo GDTCCTConstructMacClientInfo(void);
|
||||
|
||||
/** Constructs the data of a gdt_cct_NetworkConnectionInfo representing the client nework connection
|
||||
* information.
|
||||
*
|
||||
* @return The data of a gdt_cct_NetworkConnectionInfo object.
|
||||
*/
|
||||
FOUNDATION_EXPORT
|
||||
NSData *GDTCCTConstructNetworkConnectionInfoData(void);
|
||||
|
||||
/** Return a gdt_cct_NetworkConnectionInfo_MobileSubtype representing the client
|
||||
*
|
||||
* @return The gdt_cct_NetworkConnectionInfo_MobileSubtype.
|
||||
*/
|
||||
FOUNDATION_EXPORT
|
||||
gdt_cct_NetworkConnectionInfo_MobileSubtype GDTCCTNetworkConnectionInfoNetworkMobileSubtype(void);
|
||||
|
||||
#pragma mark - CCT object decoders
|
||||
|
||||
/** Decodes a gdt_cct_LogResponse given proto bytes.
|
||||
*
|
||||
* @note calloc is called in this method. Ensure that pb_release is called on the return value.
|
||||
*
|
||||
* @param data The proto bytes of the gdt_cct_LogResponse.
|
||||
* @param error An error that will be populated if something went wrong during decoding.
|
||||
* @return A newly allocated gdt_cct_LogResponse from the data, if the bytes decoded properly.
|
||||
*/
|
||||
FOUNDATION_EXPORT
|
||||
gdt_cct_LogResponse GDTCCTDecodeLogResponse(NSData *data, NSError **error);
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
29
Pods/GoogleDataTransport/GoogleDataTransport/GDTCCTLibrary/Private/GDTCCTURLSessionDataResponse.h
generated
Normal file
29
Pods/GoogleDataTransport/GoogleDataTransport/GDTCCTLibrary/Private/GDTCCTURLSessionDataResponse.h
generated
Normal file
@ -0,0 +1,29 @@
|
||||
// Copyright 2024 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/** The class represents HTTP response received from `NSURLSession`. */
|
||||
@interface GDTCCTURLSessionDataResponse : NSObject
|
||||
|
||||
@property(nonatomic, readonly) NSHTTPURLResponse *HTTPResponse;
|
||||
@property(nonatomic, nullable, readonly) NSData *HTTPBody;
|
||||
|
||||
- (instancetype)initWithResponse:(NSHTTPURLResponse *)response HTTPBody:(nullable NSData *)body;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
78
Pods/GoogleDataTransport/GoogleDataTransport/GDTCCTLibrary/Private/GDTCCTUploadOperation.h
generated
Normal file
78
Pods/GoogleDataTransport/GoogleDataTransport/GDTCCTLibrary/Private/GDTCCTUploadOperation.h
generated
Normal file
@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright 2020 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Internal/GDTCORUploader.h"
|
||||
|
||||
@protocol GDTCORStoragePromiseProtocol;
|
||||
@protocol GDTCORMetricsControllerProtocol;
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/// The protocol defines methods to retrieve/update data shared between different upload operations.
|
||||
@protocol GDTCCTUploadMetadataProvider <NSObject>
|
||||
|
||||
/** Returns a GDTCORClock object representing time after which a next upload attempt is allowed for
|
||||
* the specified target. Upload is allowed now if `nil`. */
|
||||
- (nullable GDTCORClock *)nextUploadTimeForTarget:(GDTCORTarget)target;
|
||||
|
||||
/** Stores or resets time after which a next upload attempt is allowed for the specified target. */
|
||||
- (void)setNextUploadTime:(nullable GDTCORClock *)time forTarget:(GDTCORTarget)target;
|
||||
|
||||
/** Returns an API key for the specified target. */
|
||||
- (nullable NSString *)APIKeyForTarget:(GDTCORTarget)target;
|
||||
|
||||
@end
|
||||
|
||||
/** Class capable of uploading events to the CCT backend. */
|
||||
@interface GDTCCTUploadOperation : NSOperation
|
||||
|
||||
- (instancetype)init NS_UNAVAILABLE;
|
||||
|
||||
/// Designated initializer.
|
||||
/// @param target The events target to upload.
|
||||
/// @param conditions A set of upload conditions. The conditions affect the set of events to be
|
||||
/// uploaded, e.g. events with some QoS are not uploaded on a cellular network, etc.
|
||||
/// @param uploadURL The backend URL to upload the events.
|
||||
/// @param queue A queue to dispatch async upload steps.
|
||||
/// @param storage A storage object to fetch events for upload.
|
||||
/// @param metadataProvider An object to retrieve/update data shared between upload operations.
|
||||
/// @param metricsController The metrics controller corresponding to the given target. If the given
|
||||
/// target does not support metrics controller, `nil` should be passed.
|
||||
/// @return An individual operation that can be added to an operation queue.
|
||||
- (instancetype)initWithTarget:(GDTCORTarget)target
|
||||
conditions:(GDTCORUploadConditions)conditions
|
||||
uploadURL:(NSURL *)uploadURL
|
||||
queue:(dispatch_queue_t)queue
|
||||
storage:(id<GDTCORStoragePromiseProtocol>)storage
|
||||
metadataProvider:(id<GDTCCTUploadMetadataProvider>)metadataProvider
|
||||
metricsController:(nullable id<GDTCORMetricsControllerProtocol>)metricsController
|
||||
NS_DESIGNATED_INITIALIZER;
|
||||
|
||||
/** YES if a batch upload attempt was performed. NO otherwise. If NO for the finished operation,
|
||||
* then there were no events suitable for upload. */
|
||||
@property(nonatomic, readonly) BOOL uploadAttempted;
|
||||
|
||||
/** The queue on which all CCT uploading will occur. */
|
||||
@property(nonatomic, readonly) dispatch_queue_t uploaderQueue;
|
||||
|
||||
/** The current upload task. */
|
||||
@property(nullable, nonatomic, readonly) NSURLSessionUploadTask *currentTask;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
45
Pods/GoogleDataTransport/GoogleDataTransport/GDTCCTLibrary/Private/GDTCCTUploader.h
generated
Normal file
45
Pods/GoogleDataTransport/GoogleDataTransport/GDTCCTLibrary/Private/GDTCCTUploader.h
generated
Normal file
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright 2019 Google
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Internal/GDTCORUploader.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/** Class capable of uploading events to the CCT backend. */
|
||||
@interface GDTCCTUploader : NSObject <GDTCORUploader>
|
||||
|
||||
/** Creates and/or returns the singleton instance of this class.
|
||||
*
|
||||
* @return The singleton instance of this class.
|
||||
*/
|
||||
+ (instancetype)sharedInstance;
|
||||
|
||||
#if GDT_TEST
|
||||
/** An upload URL used across all targets. For testing only. */
|
||||
@property(class, nullable, nonatomic) NSURL *testServerURL;
|
||||
|
||||
/** Spins runloop until upload finishes or timeout.
|
||||
* @return YES if upload finishes, NO in the case of timeout.
|
||||
*/
|
||||
- (BOOL)waitForUploadFinishedWithTimeout:(NSTimeInterval)timeout;
|
||||
|
||||
#endif // GDT_TEST
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
34
Pods/GoogleDataTransport/GoogleDataTransport/GDTCCTLibrary/Private/GDTCOREvent+GDTMetricsSupport.h
generated
Normal file
34
Pods/GoogleDataTransport/GoogleDataTransport/GDTCCTLibrary/Private/GDTCOREvent+GDTMetricsSupport.h
generated
Normal file
@ -0,0 +1,34 @@
|
||||
// Copyright 2022 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCOREvent.h"
|
||||
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORTargets.h"
|
||||
|
||||
@class GDTCORMetrics;
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface GDTCOREvent (GDTMetricsSupport)
|
||||
|
||||
/// Creates and returns an event for the given target with the given metrics.
|
||||
/// @param metrics The metrics to set at the event's data.
|
||||
/// @param target The backend target that the event corresponds to.
|
||||
+ (GDTCOREvent *)eventWithMetrics:(GDTCORMetrics *)metrics forTarget:(GDTCORTarget)target;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
25
Pods/GoogleDataTransport/GoogleDataTransport/GDTCCTLibrary/Private/GDTCORMetrics+GDTCCTSupport.h
generated
Normal file
25
Pods/GoogleDataTransport/GoogleDataTransport/GDTCCTLibrary/Private/GDTCORMetrics+GDTCCTSupport.h
generated
Normal file
@ -0,0 +1,25 @@
|
||||
// Copyright 2022 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Private/GDTCORMetrics.h"
|
||||
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCOREventDataObject.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface GDTCORMetrics (GDTCCTSupport) <GDTCOREventDataObject>
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
138
Pods/GoogleDataTransport/GoogleDataTransport/GDTCCTLibrary/Protogen/nanopb/cct.nanopb.c
generated
Normal file
138
Pods/GoogleDataTransport/GoogleDataTransport/GDTCCTLibrary/Protogen/nanopb/cct.nanopb.c
generated
Normal file
@ -0,0 +1,138 @@
|
||||
/*
|
||||
* Copyright 2019 Google
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/* Automatically generated nanopb constant definitions */
|
||||
/* Generated by nanopb-0.3.9.9 */
|
||||
|
||||
#include "GoogleDataTransport/GDTCCTLibrary/Protogen/nanopb/cct.nanopb.h"
|
||||
|
||||
/* @@protoc_insertion_point(includes) */
|
||||
#if PB_PROTO_HEADER_VERSION != 30
|
||||
#error Regenerate this file with the current version of nanopb generator.
|
||||
#endif
|
||||
|
||||
const gdt_cct_NetworkConnectionInfo_NetworkType gdt_cct_NetworkConnectionInfo_network_type_default = gdt_cct_NetworkConnectionInfo_NetworkType_NONE;
|
||||
const gdt_cct_NetworkConnectionInfo_MobileSubtype gdt_cct_NetworkConnectionInfo_mobile_subtype_default = gdt_cct_NetworkConnectionInfo_MobileSubtype_UNKNOWN_MOBILE_SUBTYPE;
|
||||
const gdt_cct_QosTierConfiguration_QosTier gdt_cct_LogRequest_qos_tier_default = gdt_cct_QosTierConfiguration_QosTier_DEFAULT;
|
||||
const int32_t gdt_cct_QosTierConfiguration_log_source_default = 0;
|
||||
|
||||
|
||||
const pb_field_t gdt_cct_LogEvent_fields[8] = {
|
||||
PB_FIELD( 1, INT64 , OPTIONAL, STATIC , FIRST, gdt_cct_LogEvent, event_time_ms, event_time_ms, 0),
|
||||
PB_FIELD( 6, BYTES , OPTIONAL, POINTER , OTHER, gdt_cct_LogEvent, source_extension, event_time_ms, 0),
|
||||
PB_FIELD( 11, INT32 , OPTIONAL, STATIC , OTHER, gdt_cct_LogEvent, event_code, source_extension, 0),
|
||||
PB_FIELD( 15, SINT64 , OPTIONAL, STATIC , OTHER, gdt_cct_LogEvent, timezone_offset_seconds, event_code, 0),
|
||||
PB_FIELD( 17, INT64 , OPTIONAL, STATIC , OTHER, gdt_cct_LogEvent, event_uptime_ms, timezone_offset_seconds, 0),
|
||||
PB_FIELD( 23, MESSAGE , OPTIONAL, STATIC , OTHER, gdt_cct_LogEvent, network_connection_info, event_uptime_ms, &gdt_cct_NetworkConnectionInfo_fields),
|
||||
PB_FIELD( 33, MESSAGE , OPTIONAL, STATIC , OTHER, gdt_cct_LogEvent, compliance_data, network_connection_info, &gdt_cct_ComplianceData_fields),
|
||||
PB_LAST_FIELD
|
||||
};
|
||||
|
||||
const pb_field_t gdt_cct_NetworkConnectionInfo_fields[3] = {
|
||||
PB_FIELD( 1, ENUM , OPTIONAL, STATIC , FIRST, gdt_cct_NetworkConnectionInfo, network_type, network_type, &gdt_cct_NetworkConnectionInfo_network_type_default),
|
||||
PB_FIELD( 2, UENUM , OPTIONAL, STATIC , OTHER, gdt_cct_NetworkConnectionInfo, mobile_subtype, network_type, &gdt_cct_NetworkConnectionInfo_mobile_subtype_default),
|
||||
PB_LAST_FIELD
|
||||
};
|
||||
|
||||
const pb_field_t gdt_cct_MacClientInfo_fields[5] = {
|
||||
PB_FIELD( 1, BYTES , OPTIONAL, POINTER , FIRST, gdt_cct_MacClientInfo, os_major_version, os_major_version, 0),
|
||||
PB_FIELD( 2, BYTES , OPTIONAL, POINTER , OTHER, gdt_cct_MacClientInfo, os_full_version, os_major_version, 0),
|
||||
PB_FIELD( 3, BYTES , OPTIONAL, POINTER , OTHER, gdt_cct_MacClientInfo, application_build, os_full_version, 0),
|
||||
PB_FIELD( 7, BYTES , OPTIONAL, POINTER , OTHER, gdt_cct_MacClientInfo, application_bundle_id, application_build, 0),
|
||||
PB_LAST_FIELD
|
||||
};
|
||||
|
||||
const pb_field_t gdt_cct_IosClientInfo_fields[8] = {
|
||||
PB_FIELD( 3, BYTES , OPTIONAL, POINTER , FIRST, gdt_cct_IosClientInfo, os_major_version, os_major_version, 0),
|
||||
PB_FIELD( 4, BYTES , OPTIONAL, POINTER , OTHER, gdt_cct_IosClientInfo, os_full_version, os_major_version, 0),
|
||||
PB_FIELD( 5, BYTES , OPTIONAL, POINTER , OTHER, gdt_cct_IosClientInfo, application_build, os_full_version, 0),
|
||||
PB_FIELD( 6, BYTES , OPTIONAL, POINTER , OTHER, gdt_cct_IosClientInfo, country, application_build, 0),
|
||||
PB_FIELD( 7, BYTES , OPTIONAL, POINTER , OTHER, gdt_cct_IosClientInfo, model, country, 0),
|
||||
PB_FIELD( 8, BYTES , OPTIONAL, POINTER , OTHER, gdt_cct_IosClientInfo, language_code, model, 0),
|
||||
PB_FIELD( 11, BYTES , OPTIONAL, POINTER , OTHER, gdt_cct_IosClientInfo, application_bundle_id, language_code, 0),
|
||||
PB_LAST_FIELD
|
||||
};
|
||||
|
||||
const pb_field_t gdt_cct_ClientInfo_fields[4] = {
|
||||
PB_FIELD( 1, UENUM , OPTIONAL, STATIC , FIRST, gdt_cct_ClientInfo, client_type, client_type, 0),
|
||||
PB_FIELD( 4, MESSAGE , OPTIONAL, STATIC , OTHER, gdt_cct_ClientInfo, ios_client_info, client_type, &gdt_cct_IosClientInfo_fields),
|
||||
PB_FIELD( 13, MESSAGE , OPTIONAL, STATIC , OTHER, gdt_cct_ClientInfo, mac_client_info, ios_client_info, &gdt_cct_MacClientInfo_fields),
|
||||
PB_LAST_FIELD
|
||||
};
|
||||
|
||||
const pb_field_t gdt_cct_BatchedLogRequest_fields[2] = {
|
||||
PB_FIELD( 1, MESSAGE , REPEATED, POINTER , FIRST, gdt_cct_BatchedLogRequest, log_request, log_request, &gdt_cct_LogRequest_fields),
|
||||
PB_LAST_FIELD
|
||||
};
|
||||
|
||||
const pb_field_t gdt_cct_LogRequest_fields[7] = {
|
||||
PB_FIELD( 1, MESSAGE , OPTIONAL, STATIC , FIRST, gdt_cct_LogRequest, client_info, client_info, &gdt_cct_ClientInfo_fields),
|
||||
PB_FIELD( 2, INT32 , OPTIONAL, STATIC , OTHER, gdt_cct_LogRequest, log_source, client_info, 0),
|
||||
PB_FIELD( 3, MESSAGE , REPEATED, POINTER , OTHER, gdt_cct_LogRequest, log_event, log_source, &gdt_cct_LogEvent_fields),
|
||||
PB_FIELD( 4, INT64 , OPTIONAL, STATIC , OTHER, gdt_cct_LogRequest, request_time_ms, log_event, 0),
|
||||
PB_FIELD( 8, INT64 , OPTIONAL, STATIC , OTHER, gdt_cct_LogRequest, request_uptime_ms, request_time_ms, 0),
|
||||
PB_FIELD( 9, UENUM , OPTIONAL, STATIC , OTHER, gdt_cct_LogRequest, qos_tier, request_uptime_ms, &gdt_cct_LogRequest_qos_tier_default),
|
||||
PB_LAST_FIELD
|
||||
};
|
||||
|
||||
const pb_field_t gdt_cct_QosTierConfiguration_fields[3] = {
|
||||
PB_FIELD( 2, UENUM , OPTIONAL, STATIC , FIRST, gdt_cct_QosTierConfiguration, qos_tier, qos_tier, 0),
|
||||
PB_FIELD( 3, INT32 , OPTIONAL, STATIC , OTHER, gdt_cct_QosTierConfiguration, log_source, qos_tier, &gdt_cct_QosTierConfiguration_log_source_default),
|
||||
PB_LAST_FIELD
|
||||
};
|
||||
|
||||
const pb_field_t gdt_cct_QosTiersOverride_fields[3] = {
|
||||
PB_FIELD( 1, MESSAGE , REPEATED, POINTER , FIRST, gdt_cct_QosTiersOverride, qos_tier_configuration, qos_tier_configuration, &gdt_cct_QosTierConfiguration_fields),
|
||||
PB_FIELD( 2, INT64 , OPTIONAL, STATIC , OTHER, gdt_cct_QosTiersOverride, qos_tier_fingerprint, qos_tier_configuration, 0),
|
||||
PB_LAST_FIELD
|
||||
};
|
||||
|
||||
const pb_field_t gdt_cct_LogResponse_fields[3] = {
|
||||
PB_FIELD( 1, INT64 , OPTIONAL, STATIC , FIRST, gdt_cct_LogResponse, next_request_wait_millis, next_request_wait_millis, 0),
|
||||
PB_FIELD( 3, MESSAGE , OPTIONAL, STATIC , OTHER, gdt_cct_LogResponse, qos_tier, next_request_wait_millis, &gdt_cct_QosTiersOverride_fields),
|
||||
PB_LAST_FIELD
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* Check that field information fits in pb_field_t */
|
||||
#if !defined(PB_FIELD_32BIT)
|
||||
/* If you get an error here, it means that you need to define PB_FIELD_32BIT
|
||||
* compile-time option. You can do that in pb.h or on compiler command line.
|
||||
*
|
||||
* The reason you need to do this is that some of your messages contain tag
|
||||
* numbers or field sizes that are larger than what can fit in 8 or 16 bit
|
||||
* field descriptors.
|
||||
*/
|
||||
PB_STATIC_ASSERT((pb_membersize(gdt_cct_LogEvent, network_connection_info) < 65536 && pb_membersize(gdt_cct_LogEvent, compliance_data) < 65536 && pb_membersize(gdt_cct_ClientInfo, ios_client_info) < 65536 && pb_membersize(gdt_cct_ClientInfo, mac_client_info) < 65536 && pb_membersize(gdt_cct_LogRequest, client_info) < 65536 && pb_membersize(gdt_cct_LogResponse, qos_tier) < 65536), YOU_MUST_DEFINE_PB_FIELD_32BIT_FOR_MESSAGES_gdt_cct_LogEvent_gdt_cct_NetworkConnectionInfo_gdt_cct_MacClientInfo_gdt_cct_IosClientInfo_gdt_cct_ClientInfo_gdt_cct_BatchedLogRequest_gdt_cct_LogRequest_gdt_cct_QosTierConfiguration_gdt_cct_QosTiersOverride_gdt_cct_LogResponse)
|
||||
#endif
|
||||
|
||||
#if !defined(PB_FIELD_16BIT) && !defined(PB_FIELD_32BIT)
|
||||
/* If you get an error here, it means that you need to define PB_FIELD_16BIT
|
||||
* compile-time option. You can do that in pb.h or on compiler command line.
|
||||
*
|
||||
* The reason you need to do this is that some of your messages contain tag
|
||||
* numbers or field sizes that are larger than what can fit in the default
|
||||
* 8 bit descriptors.
|
||||
*/
|
||||
PB_STATIC_ASSERT((pb_membersize(gdt_cct_LogEvent, network_connection_info) < 256 && pb_membersize(gdt_cct_LogEvent, compliance_data) < 256 && pb_membersize(gdt_cct_ClientInfo, ios_client_info) < 256 && pb_membersize(gdt_cct_ClientInfo, mac_client_info) < 256 && pb_membersize(gdt_cct_LogRequest, client_info) < 256 && pb_membersize(gdt_cct_LogResponse, qos_tier) < 256), YOU_MUST_DEFINE_PB_FIELD_16BIT_FOR_MESSAGES_gdt_cct_LogEvent_gdt_cct_NetworkConnectionInfo_gdt_cct_MacClientInfo_gdt_cct_IosClientInfo_gdt_cct_ClientInfo_gdt_cct_BatchedLogRequest_gdt_cct_LogRequest_gdt_cct_QosTierConfiguration_gdt_cct_QosTiersOverride_gdt_cct_LogResponse)
|
||||
#endif
|
||||
|
||||
|
||||
/* @@protoc_insertion_point(eof) */
|
||||
305
Pods/GoogleDataTransport/GoogleDataTransport/GDTCCTLibrary/Protogen/nanopb/cct.nanopb.h
generated
Normal file
305
Pods/GoogleDataTransport/GoogleDataTransport/GDTCCTLibrary/Protogen/nanopb/cct.nanopb.h
generated
Normal file
@ -0,0 +1,305 @@
|
||||
/*
|
||||
* Copyright 2019 Google
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/* Automatically generated nanopb header */
|
||||
/* Generated by nanopb-0.3.9.9 */
|
||||
|
||||
#ifndef PB_GDT_CCT_CCT_NANOPB_H_INCLUDED
|
||||
#define PB_GDT_CCT_CCT_NANOPB_H_INCLUDED
|
||||
#include <nanopb/pb.h>
|
||||
|
||||
#include "GoogleDataTransport/GDTCCTLibrary/Protogen/nanopb/compliance.nanopb.h"
|
||||
|
||||
/* @@protoc_insertion_point(includes) */
|
||||
#if PB_PROTO_HEADER_VERSION != 30
|
||||
#error Regenerate this file with the current version of nanopb generator.
|
||||
#endif
|
||||
|
||||
|
||||
/* Enum definitions */
|
||||
typedef enum _gdt_cct_NetworkConnectionInfo_NetworkType {
|
||||
gdt_cct_NetworkConnectionInfo_NetworkType_NONE = -1,
|
||||
gdt_cct_NetworkConnectionInfo_NetworkType_MOBILE = 0,
|
||||
gdt_cct_NetworkConnectionInfo_NetworkType_WIFI = 1,
|
||||
gdt_cct_NetworkConnectionInfo_NetworkType_MOBILE_MMS = 2,
|
||||
gdt_cct_NetworkConnectionInfo_NetworkType_MOBILE_SUPL = 3,
|
||||
gdt_cct_NetworkConnectionInfo_NetworkType_MOBILE_DUN = 4,
|
||||
gdt_cct_NetworkConnectionInfo_NetworkType_MOBILE_HIPRI = 5,
|
||||
gdt_cct_NetworkConnectionInfo_NetworkType_WIMAX = 6,
|
||||
gdt_cct_NetworkConnectionInfo_NetworkType_BLUETOOTH = 7,
|
||||
gdt_cct_NetworkConnectionInfo_NetworkType_DUMMY = 8,
|
||||
gdt_cct_NetworkConnectionInfo_NetworkType_ETHERNET = 9,
|
||||
gdt_cct_NetworkConnectionInfo_NetworkType_MOBILE_FOTA = 10,
|
||||
gdt_cct_NetworkConnectionInfo_NetworkType_MOBILE_IMS = 11,
|
||||
gdt_cct_NetworkConnectionInfo_NetworkType_MOBILE_CBS = 12,
|
||||
gdt_cct_NetworkConnectionInfo_NetworkType_WIFI_P2P = 13,
|
||||
gdt_cct_NetworkConnectionInfo_NetworkType_MOBILE_IA = 14,
|
||||
gdt_cct_NetworkConnectionInfo_NetworkType_MOBILE_EMERGENCY = 15,
|
||||
gdt_cct_NetworkConnectionInfo_NetworkType_PROXY = 16,
|
||||
gdt_cct_NetworkConnectionInfo_NetworkType_VPN = 17
|
||||
} gdt_cct_NetworkConnectionInfo_NetworkType;
|
||||
#define _gdt_cct_NetworkConnectionInfo_NetworkType_MIN gdt_cct_NetworkConnectionInfo_NetworkType_NONE
|
||||
#define _gdt_cct_NetworkConnectionInfo_NetworkType_MAX gdt_cct_NetworkConnectionInfo_NetworkType_VPN
|
||||
#define _gdt_cct_NetworkConnectionInfo_NetworkType_ARRAYSIZE ((gdt_cct_NetworkConnectionInfo_NetworkType)(gdt_cct_NetworkConnectionInfo_NetworkType_VPN+1))
|
||||
|
||||
typedef enum _gdt_cct_NetworkConnectionInfo_MobileSubtype {
|
||||
gdt_cct_NetworkConnectionInfo_MobileSubtype_UNKNOWN_MOBILE_SUBTYPE = 0,
|
||||
gdt_cct_NetworkConnectionInfo_MobileSubtype_GPRS = 1,
|
||||
gdt_cct_NetworkConnectionInfo_MobileSubtype_EDGE = 2,
|
||||
gdt_cct_NetworkConnectionInfo_MobileSubtype_UMTS = 3,
|
||||
gdt_cct_NetworkConnectionInfo_MobileSubtype_CDMA = 4,
|
||||
gdt_cct_NetworkConnectionInfo_MobileSubtype_EVDO_0 = 5,
|
||||
gdt_cct_NetworkConnectionInfo_MobileSubtype_EVDO_A = 6,
|
||||
gdt_cct_NetworkConnectionInfo_MobileSubtype_RTT = 7,
|
||||
gdt_cct_NetworkConnectionInfo_MobileSubtype_HSDPA = 8,
|
||||
gdt_cct_NetworkConnectionInfo_MobileSubtype_HSUPA = 9,
|
||||
gdt_cct_NetworkConnectionInfo_MobileSubtype_HSPA = 10,
|
||||
gdt_cct_NetworkConnectionInfo_MobileSubtype_IDEN = 11,
|
||||
gdt_cct_NetworkConnectionInfo_MobileSubtype_EVDO_B = 12,
|
||||
gdt_cct_NetworkConnectionInfo_MobileSubtype_LTE = 13,
|
||||
gdt_cct_NetworkConnectionInfo_MobileSubtype_EHRPD = 14,
|
||||
gdt_cct_NetworkConnectionInfo_MobileSubtype_HSPAP = 15,
|
||||
gdt_cct_NetworkConnectionInfo_MobileSubtype_GSM = 16,
|
||||
gdt_cct_NetworkConnectionInfo_MobileSubtype_TD_SCDMA = 17,
|
||||
gdt_cct_NetworkConnectionInfo_MobileSubtype_IWLAN = 18,
|
||||
gdt_cct_NetworkConnectionInfo_MobileSubtype_LTE_CA = 19,
|
||||
gdt_cct_NetworkConnectionInfo_MobileSubtype_COMBINED = 100
|
||||
} gdt_cct_NetworkConnectionInfo_MobileSubtype;
|
||||
#define _gdt_cct_NetworkConnectionInfo_MobileSubtype_MIN gdt_cct_NetworkConnectionInfo_MobileSubtype_UNKNOWN_MOBILE_SUBTYPE
|
||||
#define _gdt_cct_NetworkConnectionInfo_MobileSubtype_MAX gdt_cct_NetworkConnectionInfo_MobileSubtype_COMBINED
|
||||
#define _gdt_cct_NetworkConnectionInfo_MobileSubtype_ARRAYSIZE ((gdt_cct_NetworkConnectionInfo_MobileSubtype)(gdt_cct_NetworkConnectionInfo_MobileSubtype_COMBINED+1))
|
||||
|
||||
typedef enum _gdt_cct_ClientInfo_ClientType {
|
||||
gdt_cct_ClientInfo_ClientType_CLIENT_UNKNOWN = 0,
|
||||
gdt_cct_ClientInfo_ClientType_IOS_FIREBASE = 15
|
||||
} gdt_cct_ClientInfo_ClientType;
|
||||
#define _gdt_cct_ClientInfo_ClientType_MIN gdt_cct_ClientInfo_ClientType_CLIENT_UNKNOWN
|
||||
#define _gdt_cct_ClientInfo_ClientType_MAX gdt_cct_ClientInfo_ClientType_IOS_FIREBASE
|
||||
#define _gdt_cct_ClientInfo_ClientType_ARRAYSIZE ((gdt_cct_ClientInfo_ClientType)(gdt_cct_ClientInfo_ClientType_IOS_FIREBASE+1))
|
||||
|
||||
typedef enum _gdt_cct_QosTierConfiguration_QosTier {
|
||||
gdt_cct_QosTierConfiguration_QosTier_DEFAULT = 0,
|
||||
gdt_cct_QosTierConfiguration_QosTier_UNMETERED_ONLY = 1,
|
||||
gdt_cct_QosTierConfiguration_QosTier_UNMETERED_OR_DAILY = 2,
|
||||
gdt_cct_QosTierConfiguration_QosTier_FAST_IF_RADIO_AWAKE = 3,
|
||||
gdt_cct_QosTierConfiguration_QosTier_NEVER = 4
|
||||
} gdt_cct_QosTierConfiguration_QosTier;
|
||||
#define _gdt_cct_QosTierConfiguration_QosTier_MIN gdt_cct_QosTierConfiguration_QosTier_DEFAULT
|
||||
#define _gdt_cct_QosTierConfiguration_QosTier_MAX gdt_cct_QosTierConfiguration_QosTier_NEVER
|
||||
#define _gdt_cct_QosTierConfiguration_QosTier_ARRAYSIZE ((gdt_cct_QosTierConfiguration_QosTier)(gdt_cct_QosTierConfiguration_QosTier_NEVER+1))
|
||||
|
||||
/* Struct definitions */
|
||||
typedef struct _gdt_cct_BatchedLogRequest {
|
||||
pb_size_t log_request_count;
|
||||
struct _gdt_cct_LogRequest *log_request;
|
||||
/* @@protoc_insertion_point(struct:gdt_cct_BatchedLogRequest) */
|
||||
} gdt_cct_BatchedLogRequest;
|
||||
|
||||
typedef struct _gdt_cct_IosClientInfo {
|
||||
pb_bytes_array_t *os_major_version;
|
||||
pb_bytes_array_t *os_full_version;
|
||||
pb_bytes_array_t *application_build;
|
||||
pb_bytes_array_t *country;
|
||||
pb_bytes_array_t *model;
|
||||
pb_bytes_array_t *language_code;
|
||||
pb_bytes_array_t *application_bundle_id;
|
||||
/* @@protoc_insertion_point(struct:gdt_cct_IosClientInfo) */
|
||||
} gdt_cct_IosClientInfo;
|
||||
|
||||
typedef struct _gdt_cct_MacClientInfo {
|
||||
pb_bytes_array_t *os_major_version;
|
||||
pb_bytes_array_t *os_full_version;
|
||||
pb_bytes_array_t *application_build;
|
||||
pb_bytes_array_t *application_bundle_id;
|
||||
/* @@protoc_insertion_point(struct:gdt_cct_MacClientInfo) */
|
||||
} gdt_cct_MacClientInfo;
|
||||
|
||||
typedef struct _gdt_cct_ClientInfo {
|
||||
bool has_client_type;
|
||||
gdt_cct_ClientInfo_ClientType client_type;
|
||||
bool has_ios_client_info;
|
||||
gdt_cct_IosClientInfo ios_client_info;
|
||||
bool has_mac_client_info;
|
||||
gdt_cct_MacClientInfo mac_client_info;
|
||||
/* @@protoc_insertion_point(struct:gdt_cct_ClientInfo) */
|
||||
} gdt_cct_ClientInfo;
|
||||
|
||||
typedef struct _gdt_cct_NetworkConnectionInfo {
|
||||
bool has_network_type;
|
||||
gdt_cct_NetworkConnectionInfo_NetworkType network_type;
|
||||
bool has_mobile_subtype;
|
||||
gdt_cct_NetworkConnectionInfo_MobileSubtype mobile_subtype;
|
||||
/* @@protoc_insertion_point(struct:gdt_cct_NetworkConnectionInfo) */
|
||||
} gdt_cct_NetworkConnectionInfo;
|
||||
|
||||
typedef struct _gdt_cct_QosTierConfiguration {
|
||||
bool has_qos_tier;
|
||||
gdt_cct_QosTierConfiguration_QosTier qos_tier;
|
||||
bool has_log_source;
|
||||
int32_t log_source;
|
||||
/* @@protoc_insertion_point(struct:gdt_cct_QosTierConfiguration) */
|
||||
} gdt_cct_QosTierConfiguration;
|
||||
|
||||
typedef struct _gdt_cct_QosTiersOverride {
|
||||
pb_size_t qos_tier_configuration_count;
|
||||
struct _gdt_cct_QosTierConfiguration *qos_tier_configuration;
|
||||
bool has_qos_tier_fingerprint;
|
||||
int64_t qos_tier_fingerprint;
|
||||
/* @@protoc_insertion_point(struct:gdt_cct_QosTiersOverride) */
|
||||
} gdt_cct_QosTiersOverride;
|
||||
|
||||
typedef struct _gdt_cct_LogEvent {
|
||||
bool has_event_time_ms;
|
||||
int64_t event_time_ms;
|
||||
pb_bytes_array_t *source_extension;
|
||||
bool has_event_code;
|
||||
int32_t event_code;
|
||||
bool has_timezone_offset_seconds;
|
||||
int64_t timezone_offset_seconds;
|
||||
bool has_event_uptime_ms;
|
||||
int64_t event_uptime_ms;
|
||||
bool has_network_connection_info;
|
||||
gdt_cct_NetworkConnectionInfo network_connection_info;
|
||||
bool has_compliance_data;
|
||||
gdt_cct_ComplianceData compliance_data;
|
||||
/* @@protoc_insertion_point(struct:gdt_cct_LogEvent) */
|
||||
} gdt_cct_LogEvent;
|
||||
|
||||
typedef struct _gdt_cct_LogRequest {
|
||||
bool has_client_info;
|
||||
gdt_cct_ClientInfo client_info;
|
||||
bool has_log_source;
|
||||
int32_t log_source;
|
||||
pb_size_t log_event_count;
|
||||
struct _gdt_cct_LogEvent *log_event;
|
||||
bool has_request_time_ms;
|
||||
int64_t request_time_ms;
|
||||
bool has_request_uptime_ms;
|
||||
int64_t request_uptime_ms;
|
||||
bool has_qos_tier;
|
||||
gdt_cct_QosTierConfiguration_QosTier qos_tier;
|
||||
/* @@protoc_insertion_point(struct:gdt_cct_LogRequest) */
|
||||
} gdt_cct_LogRequest;
|
||||
|
||||
typedef struct _gdt_cct_LogResponse {
|
||||
bool has_next_request_wait_millis;
|
||||
int64_t next_request_wait_millis;
|
||||
bool has_qos_tier;
|
||||
gdt_cct_QosTiersOverride qos_tier;
|
||||
/* @@protoc_insertion_point(struct:gdt_cct_LogResponse) */
|
||||
} gdt_cct_LogResponse;
|
||||
|
||||
/* Default values for struct fields */
|
||||
extern const gdt_cct_NetworkConnectionInfo_NetworkType gdt_cct_NetworkConnectionInfo_network_type_default;
|
||||
extern const gdt_cct_NetworkConnectionInfo_MobileSubtype gdt_cct_NetworkConnectionInfo_mobile_subtype_default;
|
||||
extern const gdt_cct_QosTierConfiguration_QosTier gdt_cct_LogRequest_qos_tier_default;
|
||||
extern const int32_t gdt_cct_QosTierConfiguration_log_source_default;
|
||||
|
||||
/* Initializer values for message structs */
|
||||
#define gdt_cct_LogEvent_init_default {false, 0, NULL, false, 0, false, 0, false, 0, false, gdt_cct_NetworkConnectionInfo_init_default, false, gdt_cct_ComplianceData_init_default}
|
||||
#define gdt_cct_NetworkConnectionInfo_init_default {false, gdt_cct_NetworkConnectionInfo_NetworkType_NONE, false, gdt_cct_NetworkConnectionInfo_MobileSubtype_UNKNOWN_MOBILE_SUBTYPE}
|
||||
#define gdt_cct_MacClientInfo_init_default {NULL, NULL, NULL, NULL}
|
||||
#define gdt_cct_IosClientInfo_init_default {NULL, NULL, NULL, NULL, NULL, NULL, NULL}
|
||||
#define gdt_cct_ClientInfo_init_default {false, _gdt_cct_ClientInfo_ClientType_MIN, false, gdt_cct_IosClientInfo_init_default, false, gdt_cct_MacClientInfo_init_default}
|
||||
#define gdt_cct_BatchedLogRequest_init_default {0, NULL}
|
||||
#define gdt_cct_LogRequest_init_default {false, gdt_cct_ClientInfo_init_default, false, 0, 0, NULL, false, 0, false, 0, false, gdt_cct_QosTierConfiguration_QosTier_DEFAULT}
|
||||
#define gdt_cct_QosTierConfiguration_init_default {false, _gdt_cct_QosTierConfiguration_QosTier_MIN, false, 0}
|
||||
#define gdt_cct_QosTiersOverride_init_default {0, NULL, false, 0}
|
||||
#define gdt_cct_LogResponse_init_default {false, 0, false, gdt_cct_QosTiersOverride_init_default}
|
||||
#define gdt_cct_LogEvent_init_zero {false, 0, NULL, false, 0, false, 0, false, 0, false, gdt_cct_NetworkConnectionInfo_init_zero, false, gdt_cct_ComplianceData_init_zero}
|
||||
#define gdt_cct_NetworkConnectionInfo_init_zero {false, _gdt_cct_NetworkConnectionInfo_NetworkType_MIN, false, _gdt_cct_NetworkConnectionInfo_MobileSubtype_MIN}
|
||||
#define gdt_cct_MacClientInfo_init_zero {NULL, NULL, NULL, NULL}
|
||||
#define gdt_cct_IosClientInfo_init_zero {NULL, NULL, NULL, NULL, NULL, NULL, NULL}
|
||||
#define gdt_cct_ClientInfo_init_zero {false, _gdt_cct_ClientInfo_ClientType_MIN, false, gdt_cct_IosClientInfo_init_zero, false, gdt_cct_MacClientInfo_init_zero}
|
||||
#define gdt_cct_BatchedLogRequest_init_zero {0, NULL}
|
||||
#define gdt_cct_LogRequest_init_zero {false, gdt_cct_ClientInfo_init_zero, false, 0, 0, NULL, false, 0, false, 0, false, _gdt_cct_QosTierConfiguration_QosTier_MIN}
|
||||
#define gdt_cct_QosTierConfiguration_init_zero {false, _gdt_cct_QosTierConfiguration_QosTier_MIN, false, 0}
|
||||
#define gdt_cct_QosTiersOverride_init_zero {0, NULL, false, 0}
|
||||
#define gdt_cct_LogResponse_init_zero {false, 0, false, gdt_cct_QosTiersOverride_init_zero}
|
||||
|
||||
/* Field tags (for use in manual encoding/decoding) */
|
||||
#define gdt_cct_BatchedLogRequest_log_request_tag 1
|
||||
#define gdt_cct_IosClientInfo_os_major_version_tag 3
|
||||
#define gdt_cct_IosClientInfo_os_full_version_tag 4
|
||||
#define gdt_cct_IosClientInfo_application_build_tag 5
|
||||
#define gdt_cct_IosClientInfo_country_tag 6
|
||||
#define gdt_cct_IosClientInfo_model_tag 7
|
||||
#define gdt_cct_IosClientInfo_language_code_tag 8
|
||||
#define gdt_cct_IosClientInfo_application_bundle_id_tag 11
|
||||
#define gdt_cct_MacClientInfo_os_major_version_tag 1
|
||||
#define gdt_cct_MacClientInfo_os_full_version_tag 2
|
||||
#define gdt_cct_MacClientInfo_application_build_tag 3
|
||||
#define gdt_cct_MacClientInfo_application_bundle_id_tag 7
|
||||
#define gdt_cct_ClientInfo_client_type_tag 1
|
||||
#define gdt_cct_ClientInfo_ios_client_info_tag 4
|
||||
#define gdt_cct_ClientInfo_mac_client_info_tag 13
|
||||
#define gdt_cct_NetworkConnectionInfo_network_type_tag 1
|
||||
#define gdt_cct_NetworkConnectionInfo_mobile_subtype_tag 2
|
||||
#define gdt_cct_QosTierConfiguration_qos_tier_tag 2
|
||||
#define gdt_cct_QosTierConfiguration_log_source_tag 3
|
||||
#define gdt_cct_QosTiersOverride_qos_tier_configuration_tag 1
|
||||
#define gdt_cct_QosTiersOverride_qos_tier_fingerprint_tag 2
|
||||
#define gdt_cct_LogEvent_event_time_ms_tag 1
|
||||
#define gdt_cct_LogEvent_event_code_tag 11
|
||||
#define gdt_cct_LogEvent_event_uptime_ms_tag 17
|
||||
#define gdt_cct_LogEvent_source_extension_tag 6
|
||||
#define gdt_cct_LogEvent_timezone_offset_seconds_tag 15
|
||||
#define gdt_cct_LogEvent_network_connection_info_tag 23
|
||||
#define gdt_cct_LogEvent_compliance_data_tag 33
|
||||
#define gdt_cct_LogRequest_request_time_ms_tag 4
|
||||
#define gdt_cct_LogRequest_request_uptime_ms_tag 8
|
||||
#define gdt_cct_LogRequest_client_info_tag 1
|
||||
#define gdt_cct_LogRequest_log_source_tag 2
|
||||
#define gdt_cct_LogRequest_log_event_tag 3
|
||||
#define gdt_cct_LogRequest_qos_tier_tag 9
|
||||
#define gdt_cct_LogResponse_next_request_wait_millis_tag 1
|
||||
#define gdt_cct_LogResponse_qos_tier_tag 3
|
||||
|
||||
/* Struct field encoding specification for nanopb */
|
||||
extern const pb_field_t gdt_cct_LogEvent_fields[8];
|
||||
extern const pb_field_t gdt_cct_NetworkConnectionInfo_fields[3];
|
||||
extern const pb_field_t gdt_cct_MacClientInfo_fields[5];
|
||||
extern const pb_field_t gdt_cct_IosClientInfo_fields[8];
|
||||
extern const pb_field_t gdt_cct_ClientInfo_fields[4];
|
||||
extern const pb_field_t gdt_cct_BatchedLogRequest_fields[2];
|
||||
extern const pb_field_t gdt_cct_LogRequest_fields[7];
|
||||
extern const pb_field_t gdt_cct_QosTierConfiguration_fields[3];
|
||||
extern const pb_field_t gdt_cct_QosTiersOverride_fields[3];
|
||||
extern const pb_field_t gdt_cct_LogResponse_fields[3];
|
||||
|
||||
/* Maximum encoded size of messages (where known) */
|
||||
/* gdt_cct_LogEvent_size depends on runtime parameters */
|
||||
#define gdt_cct_NetworkConnectionInfo_size 13
|
||||
/* gdt_cct_MacClientInfo_size depends on runtime parameters */
|
||||
/* gdt_cct_IosClientInfo_size depends on runtime parameters */
|
||||
/* gdt_cct_ClientInfo_size depends on runtime parameters */
|
||||
/* gdt_cct_BatchedLogRequest_size depends on runtime parameters */
|
||||
/* gdt_cct_LogRequest_size depends on runtime parameters */
|
||||
#define gdt_cct_QosTierConfiguration_size 13
|
||||
/* gdt_cct_QosTiersOverride_size depends on runtime parameters */
|
||||
/* gdt_cct_LogResponse_size depends on runtime parameters */
|
||||
|
||||
/* Message IDs (where set with "msgid" option) */
|
||||
#ifdef PB_MSGID
|
||||
|
||||
#define CCT_MESSAGES \
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
/* @@protoc_insertion_point(eof) */
|
||||
|
||||
#endif
|
||||
92
Pods/GoogleDataTransport/GoogleDataTransport/GDTCCTLibrary/Protogen/nanopb/client_metrics.nanopb.c
generated
Normal file
92
Pods/GoogleDataTransport/GoogleDataTransport/GDTCCTLibrary/Protogen/nanopb/client_metrics.nanopb.c
generated
Normal file
@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright 2022 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/* Automatically generated nanopb constant definitions */
|
||||
/* Generated by nanopb-0.3.9.9 */
|
||||
|
||||
#include "GoogleDataTransport/GDTCCTLibrary/Protogen/nanopb/client_metrics.nanopb.h"
|
||||
|
||||
/* @@protoc_insertion_point(includes) */
|
||||
#if PB_PROTO_HEADER_VERSION != 30
|
||||
#error Regenerate this file with the current version of nanopb generator.
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
const pb_field_t gdt_client_metrics_ClientMetrics_fields[5] = {
|
||||
PB_FIELD( 1, MESSAGE , SINGULAR, STATIC , FIRST, gdt_client_metrics_ClientMetrics, window, window, &gdt_client_metrics_TimeWindow_fields),
|
||||
PB_FIELD( 2, MESSAGE , REPEATED, POINTER , OTHER, gdt_client_metrics_ClientMetrics, log_source_metrics, window, &gdt_client_metrics_LogSourceMetrics_fields),
|
||||
PB_FIELD( 3, MESSAGE , SINGULAR, STATIC , OTHER, gdt_client_metrics_ClientMetrics, global_metrics, log_source_metrics, &gdt_client_metrics_GlobalMetrics_fields),
|
||||
PB_FIELD( 4, BYTES , SINGULAR, POINTER , OTHER, gdt_client_metrics_ClientMetrics, app_namespace, global_metrics, 0),
|
||||
PB_LAST_FIELD
|
||||
};
|
||||
|
||||
const pb_field_t gdt_client_metrics_TimeWindow_fields[3] = {
|
||||
PB_FIELD( 1, INT64 , SINGULAR, STATIC , FIRST, gdt_client_metrics_TimeWindow, start_ms, start_ms, 0),
|
||||
PB_FIELD( 2, INT64 , SINGULAR, STATIC , OTHER, gdt_client_metrics_TimeWindow, end_ms, start_ms, 0),
|
||||
PB_LAST_FIELD
|
||||
};
|
||||
|
||||
const pb_field_t gdt_client_metrics_GlobalMetrics_fields[2] = {
|
||||
PB_FIELD( 1, MESSAGE , SINGULAR, STATIC , FIRST, gdt_client_metrics_GlobalMetrics, storage_metrics, storage_metrics, &gdt_client_metrics_StorageMetrics_fields),
|
||||
PB_LAST_FIELD
|
||||
};
|
||||
|
||||
const pb_field_t gdt_client_metrics_StorageMetrics_fields[3] = {
|
||||
PB_FIELD( 1, INT64 , SINGULAR, STATIC , FIRST, gdt_client_metrics_StorageMetrics, current_cache_size_bytes, current_cache_size_bytes, 0),
|
||||
PB_FIELD( 2, INT64 , SINGULAR, STATIC , OTHER, gdt_client_metrics_StorageMetrics, max_cache_size_bytes, current_cache_size_bytes, 0),
|
||||
PB_LAST_FIELD
|
||||
};
|
||||
|
||||
const pb_field_t gdt_client_metrics_LogSourceMetrics_fields[3] = {
|
||||
PB_FIELD( 1, BYTES , SINGULAR, POINTER , FIRST, gdt_client_metrics_LogSourceMetrics, log_source, log_source, 0),
|
||||
PB_FIELD( 2, MESSAGE , REPEATED, POINTER , OTHER, gdt_client_metrics_LogSourceMetrics, log_event_dropped, log_source, &gdt_client_metrics_LogEventDropped_fields),
|
||||
PB_LAST_FIELD
|
||||
};
|
||||
|
||||
const pb_field_t gdt_client_metrics_LogEventDropped_fields[3] = {
|
||||
PB_FIELD( 1, INT64 , SINGULAR, STATIC , FIRST, gdt_client_metrics_LogEventDropped, events_dropped_count, events_dropped_count, 0),
|
||||
PB_FIELD( 3, UENUM , SINGULAR, STATIC , OTHER, gdt_client_metrics_LogEventDropped, reason, events_dropped_count, 0),
|
||||
PB_LAST_FIELD
|
||||
};
|
||||
|
||||
|
||||
|
||||
/* Check that field information fits in pb_field_t */
|
||||
#if !defined(PB_FIELD_32BIT)
|
||||
/* If you get an error here, it means that you need to define PB_FIELD_32BIT
|
||||
* compile-time option. You can do that in pb.h or on compiler command line.
|
||||
*
|
||||
* The reason you need to do this is that some of your messages contain tag
|
||||
* numbers or field sizes that are larger than what can fit in 8 or 16 bit
|
||||
* field descriptors.
|
||||
*/
|
||||
PB_STATIC_ASSERT((pb_membersize(gdt_client_metrics_ClientMetrics, window) < 65536 && pb_membersize(gdt_client_metrics_ClientMetrics, global_metrics) < 65536 && pb_membersize(gdt_client_metrics_GlobalMetrics, storage_metrics) < 65536), YOU_MUST_DEFINE_PB_FIELD_32BIT_FOR_MESSAGES_gdt_client_metrics_ClientMetrics_gdt_client_metrics_TimeWindow_gdt_client_metrics_GlobalMetrics_gdt_client_metrics_StorageMetrics_gdt_client_metrics_LogSourceMetrics_gdt_client_metrics_LogEventDropped)
|
||||
#endif
|
||||
|
||||
#if !defined(PB_FIELD_16BIT) && !defined(PB_FIELD_32BIT)
|
||||
/* If you get an error here, it means that you need to define PB_FIELD_16BIT
|
||||
* compile-time option. You can do that in pb.h or on compiler command line.
|
||||
*
|
||||
* The reason you need to do this is that some of your messages contain tag
|
||||
* numbers or field sizes that are larger than what can fit in the default
|
||||
* 8 bit descriptors.
|
||||
*/
|
||||
PB_STATIC_ASSERT((pb_membersize(gdt_client_metrics_ClientMetrics, window) < 256 && pb_membersize(gdt_client_metrics_ClientMetrics, global_metrics) < 256 && pb_membersize(gdt_client_metrics_GlobalMetrics, storage_metrics) < 256), YOU_MUST_DEFINE_PB_FIELD_16BIT_FOR_MESSAGES_gdt_client_metrics_ClientMetrics_gdt_client_metrics_TimeWindow_gdt_client_metrics_GlobalMetrics_gdt_client_metrics_StorageMetrics_gdt_client_metrics_LogSourceMetrics_gdt_client_metrics_LogEventDropped)
|
||||
#endif
|
||||
|
||||
|
||||
/* @@protoc_insertion_point(eof) */
|
||||
141
Pods/GoogleDataTransport/GoogleDataTransport/GDTCCTLibrary/Protogen/nanopb/client_metrics.nanopb.h
generated
Normal file
141
Pods/GoogleDataTransport/GoogleDataTransport/GDTCCTLibrary/Protogen/nanopb/client_metrics.nanopb.h
generated
Normal file
@ -0,0 +1,141 @@
|
||||
/*
|
||||
* Copyright 2022 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/* Automatically generated nanopb header */
|
||||
/* Generated by nanopb-0.3.9.9 */
|
||||
|
||||
#ifndef PB_GDT_CLIENT_METRICS_CLIENT_METRICS_NANOPB_H_INCLUDED
|
||||
#define PB_GDT_CLIENT_METRICS_CLIENT_METRICS_NANOPB_H_INCLUDED
|
||||
#include <nanopb/pb.h>
|
||||
|
||||
/* @@protoc_insertion_point(includes) */
|
||||
#if PB_PROTO_HEADER_VERSION != 30
|
||||
#error Regenerate this file with the current version of nanopb generator.
|
||||
#endif
|
||||
|
||||
|
||||
/* Enum definitions */
|
||||
typedef enum _gdt_client_metrics_LogEventDropped_Reason {
|
||||
gdt_client_metrics_LogEventDropped_Reason_REASON_UNKNOWN = 0,
|
||||
gdt_client_metrics_LogEventDropped_Reason_MESSAGE_TOO_OLD = 1,
|
||||
gdt_client_metrics_LogEventDropped_Reason_CACHE_FULL = 2,
|
||||
gdt_client_metrics_LogEventDropped_Reason_PAYLOAD_TOO_BIG = 3,
|
||||
gdt_client_metrics_LogEventDropped_Reason_MAX_RETRIES_REACHED = 4,
|
||||
gdt_client_metrics_LogEventDropped_Reason_INVALID_PAYLOD = 5,
|
||||
gdt_client_metrics_LogEventDropped_Reason_SERVER_ERROR = 6
|
||||
} gdt_client_metrics_LogEventDropped_Reason;
|
||||
#define _gdt_client_metrics_LogEventDropped_Reason_MIN gdt_client_metrics_LogEventDropped_Reason_REASON_UNKNOWN
|
||||
#define _gdt_client_metrics_LogEventDropped_Reason_MAX gdt_client_metrics_LogEventDropped_Reason_SERVER_ERROR
|
||||
#define _gdt_client_metrics_LogEventDropped_Reason_ARRAYSIZE ((gdt_client_metrics_LogEventDropped_Reason)(gdt_client_metrics_LogEventDropped_Reason_SERVER_ERROR+1))
|
||||
|
||||
/* Struct definitions */
|
||||
typedef struct _gdt_client_metrics_LogSourceMetrics {
|
||||
pb_bytes_array_t *log_source;
|
||||
pb_size_t log_event_dropped_count;
|
||||
struct _gdt_client_metrics_LogEventDropped *log_event_dropped;
|
||||
/* @@protoc_insertion_point(struct:gdt_client_metrics_LogSourceMetrics) */
|
||||
} gdt_client_metrics_LogSourceMetrics;
|
||||
|
||||
typedef struct _gdt_client_metrics_LogEventDropped {
|
||||
int64_t events_dropped_count;
|
||||
gdt_client_metrics_LogEventDropped_Reason reason;
|
||||
/* @@protoc_insertion_point(struct:gdt_client_metrics_LogEventDropped) */
|
||||
} gdt_client_metrics_LogEventDropped;
|
||||
|
||||
typedef struct _gdt_client_metrics_StorageMetrics {
|
||||
int64_t current_cache_size_bytes;
|
||||
int64_t max_cache_size_bytes;
|
||||
/* @@protoc_insertion_point(struct:gdt_client_metrics_StorageMetrics) */
|
||||
} gdt_client_metrics_StorageMetrics;
|
||||
|
||||
typedef struct _gdt_client_metrics_TimeWindow {
|
||||
int64_t start_ms;
|
||||
int64_t end_ms;
|
||||
/* @@protoc_insertion_point(struct:gdt_client_metrics_TimeWindow) */
|
||||
} gdt_client_metrics_TimeWindow;
|
||||
|
||||
typedef struct _gdt_client_metrics_GlobalMetrics {
|
||||
gdt_client_metrics_StorageMetrics storage_metrics;
|
||||
/* @@protoc_insertion_point(struct:gdt_client_metrics_GlobalMetrics) */
|
||||
} gdt_client_metrics_GlobalMetrics;
|
||||
|
||||
typedef struct _gdt_client_metrics_ClientMetrics {
|
||||
gdt_client_metrics_TimeWindow window;
|
||||
pb_size_t log_source_metrics_count;
|
||||
struct _gdt_client_metrics_LogSourceMetrics *log_source_metrics;
|
||||
gdt_client_metrics_GlobalMetrics global_metrics;
|
||||
pb_bytes_array_t *app_namespace;
|
||||
/* @@protoc_insertion_point(struct:gdt_client_metrics_ClientMetrics) */
|
||||
} gdt_client_metrics_ClientMetrics;
|
||||
|
||||
/* Default values for struct fields */
|
||||
|
||||
/* Initializer values for message structs */
|
||||
#define gdt_client_metrics_ClientMetrics_init_default {gdt_client_metrics_TimeWindow_init_default, 0, NULL, gdt_client_metrics_GlobalMetrics_init_default, NULL}
|
||||
#define gdt_client_metrics_TimeWindow_init_default {0, 0}
|
||||
#define gdt_client_metrics_GlobalMetrics_init_default {gdt_client_metrics_StorageMetrics_init_default}
|
||||
#define gdt_client_metrics_StorageMetrics_init_default {0, 0}
|
||||
#define gdt_client_metrics_LogSourceMetrics_init_default {NULL, 0, NULL}
|
||||
#define gdt_client_metrics_LogEventDropped_init_default {0, _gdt_client_metrics_LogEventDropped_Reason_MIN}
|
||||
#define gdt_client_metrics_ClientMetrics_init_zero {gdt_client_metrics_TimeWindow_init_zero, 0, NULL, gdt_client_metrics_GlobalMetrics_init_zero, NULL}
|
||||
#define gdt_client_metrics_TimeWindow_init_zero {0, 0}
|
||||
#define gdt_client_metrics_GlobalMetrics_init_zero {gdt_client_metrics_StorageMetrics_init_zero}
|
||||
#define gdt_client_metrics_StorageMetrics_init_zero {0, 0}
|
||||
#define gdt_client_metrics_LogSourceMetrics_init_zero {NULL, 0, NULL}
|
||||
#define gdt_client_metrics_LogEventDropped_init_zero {0, _gdt_client_metrics_LogEventDropped_Reason_MIN}
|
||||
|
||||
/* Field tags (for use in manual encoding/decoding) */
|
||||
#define gdt_client_metrics_LogSourceMetrics_log_source_tag 1
|
||||
#define gdt_client_metrics_LogSourceMetrics_log_event_dropped_tag 2
|
||||
#define gdt_client_metrics_LogEventDropped_events_dropped_count_tag 1
|
||||
#define gdt_client_metrics_LogEventDropped_reason_tag 3
|
||||
#define gdt_client_metrics_StorageMetrics_current_cache_size_bytes_tag 1
|
||||
#define gdt_client_metrics_StorageMetrics_max_cache_size_bytes_tag 2
|
||||
#define gdt_client_metrics_TimeWindow_start_ms_tag 1
|
||||
#define gdt_client_metrics_TimeWindow_end_ms_tag 2
|
||||
#define gdt_client_metrics_GlobalMetrics_storage_metrics_tag 1
|
||||
#define gdt_client_metrics_ClientMetrics_window_tag 1
|
||||
#define gdt_client_metrics_ClientMetrics_log_source_metrics_tag 2
|
||||
#define gdt_client_metrics_ClientMetrics_global_metrics_tag 3
|
||||
#define gdt_client_metrics_ClientMetrics_app_namespace_tag 4
|
||||
|
||||
/* Struct field encoding specification for nanopb */
|
||||
extern const pb_field_t gdt_client_metrics_ClientMetrics_fields[5];
|
||||
extern const pb_field_t gdt_client_metrics_TimeWindow_fields[3];
|
||||
extern const pb_field_t gdt_client_metrics_GlobalMetrics_fields[2];
|
||||
extern const pb_field_t gdt_client_metrics_StorageMetrics_fields[3];
|
||||
extern const pb_field_t gdt_client_metrics_LogSourceMetrics_fields[3];
|
||||
extern const pb_field_t gdt_client_metrics_LogEventDropped_fields[3];
|
||||
|
||||
/* Maximum encoded size of messages (where known) */
|
||||
/* gdt_client_metrics_ClientMetrics_size depends on runtime parameters */
|
||||
#define gdt_client_metrics_TimeWindow_size 22
|
||||
#define gdt_client_metrics_GlobalMetrics_size 24
|
||||
#define gdt_client_metrics_StorageMetrics_size 22
|
||||
/* gdt_client_metrics_LogSourceMetrics_size depends on runtime parameters */
|
||||
#define gdt_client_metrics_LogEventDropped_size 13
|
||||
|
||||
/* Message IDs (where set with "msgid" option) */
|
||||
#ifdef PB_MSGID
|
||||
|
||||
#define CLIENT_METRICS_MESSAGES \
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
/* @@protoc_insertion_point(eof) */
|
||||
|
||||
#endif
|
||||
62
Pods/GoogleDataTransport/GoogleDataTransport/GDTCCTLibrary/Protogen/nanopb/compliance.nanopb.c
generated
Normal file
62
Pods/GoogleDataTransport/GoogleDataTransport/GDTCCTLibrary/Protogen/nanopb/compliance.nanopb.c
generated
Normal file
@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright 2023 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/* Automatically generated nanopb constant definitions */
|
||||
/* Generated by nanopb-0.3.9.9 */
|
||||
|
||||
#include "GoogleDataTransport/GDTCCTLibrary/Protogen/nanopb/compliance.nanopb.h"
|
||||
|
||||
/* @@protoc_insertion_point(includes) */
|
||||
#if PB_PROTO_HEADER_VERSION != 30
|
||||
#error Regenerate this file with the current version of nanopb generator.
|
||||
#endif
|
||||
|
||||
const gdt_cct_ComplianceData_ProductIdOrigin gdt_cct_ComplianceData_product_id_origin_default = gdt_cct_ComplianceData_ProductIdOrigin_NOT_SET;
|
||||
|
||||
|
||||
const pb_field_t gdt_cct_ComplianceData_fields[3] = {
|
||||
PB_FIELD( 1, MESSAGE , OPTIONAL, STATIC , FIRST, gdt_cct_ComplianceData, privacy_context, privacy_context, &privacy_context_external_ExternalPrivacyContext_fields),
|
||||
PB_FIELD( 2, UENUM , OPTIONAL, STATIC , OTHER, gdt_cct_ComplianceData, product_id_origin, privacy_context, &gdt_cct_ComplianceData_product_id_origin_default),
|
||||
PB_LAST_FIELD
|
||||
};
|
||||
|
||||
|
||||
|
||||
/* Check that field information fits in pb_field_t */
|
||||
#if !defined(PB_FIELD_32BIT)
|
||||
/* If you get an error here, it means that you need to define PB_FIELD_32BIT
|
||||
* compile-time option. You can do that in pb.h or on compiler command line.
|
||||
*
|
||||
* The reason you need to do this is that some of your messages contain tag
|
||||
* numbers or field sizes that are larger than what can fit in 8 or 16 bit
|
||||
* field descriptors.
|
||||
*/
|
||||
PB_STATIC_ASSERT((pb_membersize(gdt_cct_ComplianceData, privacy_context) < 65536), YOU_MUST_DEFINE_PB_FIELD_32BIT_FOR_MESSAGES_gdt_cct_ComplianceData)
|
||||
#endif
|
||||
|
||||
#if !defined(PB_FIELD_16BIT) && !defined(PB_FIELD_32BIT)
|
||||
/* If you get an error here, it means that you need to define PB_FIELD_16BIT
|
||||
* compile-time option. You can do that in pb.h or on compiler command line.
|
||||
*
|
||||
* The reason you need to do this is that some of your messages contain tag
|
||||
* numbers or field sizes that are larger than what can fit in the default
|
||||
* 8 bit descriptors.
|
||||
*/
|
||||
PB_STATIC_ASSERT((pb_membersize(gdt_cct_ComplianceData, privacy_context) < 256), YOU_MUST_DEFINE_PB_FIELD_16BIT_FOR_MESSAGES_gdt_cct_ComplianceData)
|
||||
#endif
|
||||
|
||||
|
||||
/* @@protoc_insertion_point(eof) */
|
||||
77
Pods/GoogleDataTransport/GoogleDataTransport/GDTCCTLibrary/Protogen/nanopb/compliance.nanopb.h
generated
Normal file
77
Pods/GoogleDataTransport/GoogleDataTransport/GDTCCTLibrary/Protogen/nanopb/compliance.nanopb.h
generated
Normal file
@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright 2023 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/* Automatically generated nanopb header */
|
||||
/* Generated by nanopb-0.3.9.9 */
|
||||
|
||||
#ifndef PB_GDT_CCT_COMPLIANCE_NANOPB_H_INCLUDED
|
||||
#define PB_GDT_CCT_COMPLIANCE_NANOPB_H_INCLUDED
|
||||
#include <nanopb/pb.h>
|
||||
|
||||
#include "GoogleDataTransport/GDTCCTLibrary/Protogen/nanopb/external_privacy_context.nanopb.h"
|
||||
|
||||
/* @@protoc_insertion_point(includes) */
|
||||
#if PB_PROTO_HEADER_VERSION != 30
|
||||
#error Regenerate this file with the current version of nanopb generator.
|
||||
#endif
|
||||
|
||||
|
||||
/* Enum definitions */
|
||||
typedef enum _gdt_cct_ComplianceData_ProductIdOrigin {
|
||||
gdt_cct_ComplianceData_ProductIdOrigin_NOT_SET = 0,
|
||||
gdt_cct_ComplianceData_ProductIdOrigin_EVENT_OVERRIDE = 5
|
||||
} gdt_cct_ComplianceData_ProductIdOrigin;
|
||||
#define _gdt_cct_ComplianceData_ProductIdOrigin_MIN gdt_cct_ComplianceData_ProductIdOrigin_NOT_SET
|
||||
#define _gdt_cct_ComplianceData_ProductIdOrigin_MAX gdt_cct_ComplianceData_ProductIdOrigin_EVENT_OVERRIDE
|
||||
#define _gdt_cct_ComplianceData_ProductIdOrigin_ARRAYSIZE ((gdt_cct_ComplianceData_ProductIdOrigin)(gdt_cct_ComplianceData_ProductIdOrigin_EVENT_OVERRIDE+1))
|
||||
|
||||
/* Struct definitions */
|
||||
typedef struct _gdt_cct_ComplianceData {
|
||||
bool has_privacy_context;
|
||||
privacy_context_external_ExternalPrivacyContext privacy_context;
|
||||
bool has_product_id_origin;
|
||||
gdt_cct_ComplianceData_ProductIdOrigin product_id_origin;
|
||||
/* @@protoc_insertion_point(struct:gdt_cct_ComplianceData) */
|
||||
} gdt_cct_ComplianceData;
|
||||
|
||||
/* Default values for struct fields */
|
||||
extern const gdt_cct_ComplianceData_ProductIdOrigin gdt_cct_ComplianceData_product_id_origin_default;
|
||||
|
||||
/* Initializer values for message structs */
|
||||
#define gdt_cct_ComplianceData_init_default {false, privacy_context_external_ExternalPrivacyContext_init_default, false, gdt_cct_ComplianceData_ProductIdOrigin_NOT_SET}
|
||||
#define gdt_cct_ComplianceData_init_zero {false, privacy_context_external_ExternalPrivacyContext_init_zero, false, _gdt_cct_ComplianceData_ProductIdOrigin_MIN}
|
||||
|
||||
/* Field tags (for use in manual encoding/decoding) */
|
||||
#define gdt_cct_ComplianceData_privacy_context_tag 1
|
||||
#define gdt_cct_ComplianceData_product_id_origin_tag 2
|
||||
|
||||
/* Struct field encoding specification for nanopb */
|
||||
extern const pb_field_t gdt_cct_ComplianceData_fields[3];
|
||||
|
||||
/* Maximum encoded size of messages (where known) */
|
||||
#define gdt_cct_ComplianceData_size (14 + privacy_context_external_ExternalPRequestContext_size)
|
||||
|
||||
/* Message IDs (where set with "msgid" option) */
|
||||
#ifdef PB_MSGID
|
||||
|
||||
#define COMPLIANCE_MESSAGES \
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
/* @@protoc_insertion_point(eof) */
|
||||
|
||||
#endif
|
||||
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright 2023 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/* Automatically generated nanopb constant definitions */
|
||||
/* Generated by nanopb-0.3.9.9 */
|
||||
|
||||
#include "GoogleDataTransport/GDTCCTLibrary/Protogen/nanopb/external_prequest_context.nanopb.h"
|
||||
|
||||
/* @@protoc_insertion_point(includes) */
|
||||
#if PB_PROTO_HEADER_VERSION != 30
|
||||
#error Regenerate this file with the current version of nanopb generator.
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
const pb_field_t privacy_context_external_ExternalPRequestContext_fields[2] = {
|
||||
PB_FIELD( 13, INT32 , OPTIONAL, STATIC , FIRST, privacy_context_external_ExternalPRequestContext, origin_associated_product_id, origin_associated_product_id, 0),
|
||||
PB_LAST_FIELD
|
||||
};
|
||||
|
||||
|
||||
/* @@protoc_insertion_point(eof) */
|
||||
@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright 2023 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/* Automatically generated nanopb header */
|
||||
/* Generated by nanopb-0.3.9.9 */
|
||||
|
||||
#ifndef PB_PRIVACY_CONTEXT_EXTERNAL_EXTERNAL_PREQUEST_CONTEXT_NANOPB_H_INCLUDED
|
||||
#define PB_PRIVACY_CONTEXT_EXTERNAL_EXTERNAL_PREQUEST_CONTEXT_NANOPB_H_INCLUDED
|
||||
#include <nanopb/pb.h>
|
||||
|
||||
/* @@protoc_insertion_point(includes) */
|
||||
#if PB_PROTO_HEADER_VERSION != 30
|
||||
#error Regenerate this file with the current version of nanopb generator.
|
||||
#endif
|
||||
|
||||
|
||||
/* Struct definitions */
|
||||
typedef struct _privacy_context_external_ExternalPRequestContext {
|
||||
bool has_origin_associated_product_id;
|
||||
int32_t origin_associated_product_id;
|
||||
/* @@protoc_insertion_point(struct:privacy_context_external_ExternalPRequestContext) */
|
||||
} privacy_context_external_ExternalPRequestContext;
|
||||
|
||||
/* Default values for struct fields */
|
||||
|
||||
/* Initializer values for message structs */
|
||||
#define privacy_context_external_ExternalPRequestContext_init_default {false, 0}
|
||||
#define privacy_context_external_ExternalPRequestContext_init_zero {false, 0}
|
||||
|
||||
/* Field tags (for use in manual encoding/decoding) */
|
||||
#define privacy_context_external_ExternalPRequestContext_origin_associated_product_id_tag 13
|
||||
|
||||
/* Struct field encoding specification for nanopb */
|
||||
extern const pb_field_t privacy_context_external_ExternalPRequestContext_fields[2];
|
||||
|
||||
/* Maximum encoded size of messages (where known) */
|
||||
#define privacy_context_external_ExternalPRequestContext_size 11
|
||||
|
||||
/* Message IDs (where set with "msgid" option) */
|
||||
#ifdef PB_MSGID
|
||||
|
||||
#define EXTERNAL_PREQUEST_CONTEXT_MESSAGES \
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
/* @@protoc_insertion_point(eof) */
|
||||
|
||||
#endif
|
||||
@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright 2023 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/* Automatically generated nanopb constant definitions */
|
||||
/* Generated by nanopb-0.3.9.9 */
|
||||
|
||||
#include "GoogleDataTransport/GDTCCTLibrary/Protogen/nanopb/external_privacy_context.nanopb.h"
|
||||
|
||||
/* @@protoc_insertion_point(includes) */
|
||||
#if PB_PROTO_HEADER_VERSION != 30
|
||||
#error Regenerate this file with the current version of nanopb generator.
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
const pb_field_t privacy_context_external_ExternalPrivacyContext_fields[2] = {
|
||||
PB_FIELD( 2, MESSAGE , OPTIONAL, STATIC , FIRST, privacy_context_external_ExternalPrivacyContext, prequest, prequest, &privacy_context_external_ExternalPRequestContext_fields),
|
||||
PB_LAST_FIELD
|
||||
};
|
||||
|
||||
|
||||
/* Check that field information fits in pb_field_t */
|
||||
#if !defined(PB_FIELD_32BIT)
|
||||
/* If you get an error here, it means that you need to define PB_FIELD_32BIT
|
||||
* compile-time option. You can do that in pb.h or on compiler command line.
|
||||
*
|
||||
* The reason you need to do this is that some of your messages contain tag
|
||||
* numbers or field sizes that are larger than what can fit in 8 or 16 bit
|
||||
* field descriptors.
|
||||
*/
|
||||
PB_STATIC_ASSERT((pb_membersize(privacy_context_external_ExternalPrivacyContext, prequest) < 65536), YOU_MUST_DEFINE_PB_FIELD_32BIT_FOR_MESSAGES_privacy_context_external_ExternalPrivacyContext)
|
||||
#endif
|
||||
|
||||
#if !defined(PB_FIELD_16BIT) && !defined(PB_FIELD_32BIT)
|
||||
/* If you get an error here, it means that you need to define PB_FIELD_16BIT
|
||||
* compile-time option. You can do that in pb.h or on compiler command line.
|
||||
*
|
||||
* The reason you need to do this is that some of your messages contain tag
|
||||
* numbers or field sizes that are larger than what can fit in the default
|
||||
* 8 bit descriptors.
|
||||
*/
|
||||
PB_STATIC_ASSERT((pb_membersize(privacy_context_external_ExternalPrivacyContext, prequest) < 256), YOU_MUST_DEFINE_PB_FIELD_16BIT_FOR_MESSAGES_privacy_context_external_ExternalPrivacyContext)
|
||||
#endif
|
||||
|
||||
|
||||
/* @@protoc_insertion_point(eof) */
|
||||
@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright 2023 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/* Automatically generated nanopb header */
|
||||
/* Generated by nanopb-0.3.9.9 */
|
||||
|
||||
#ifndef PB_PRIVACY_CONTEXT_EXTERNAL_EXTERNAL_PRIVACY_CONTEXT_NANOPB_H_INCLUDED
|
||||
#define PB_PRIVACY_CONTEXT_EXTERNAL_EXTERNAL_PRIVACY_CONTEXT_NANOPB_H_INCLUDED
|
||||
#include <nanopb/pb.h>
|
||||
|
||||
#include "GoogleDataTransport/GDTCCTLibrary/Protogen/nanopb/external_prequest_context.nanopb.h"
|
||||
|
||||
/* @@protoc_insertion_point(includes) */
|
||||
#if PB_PROTO_HEADER_VERSION != 30
|
||||
#error Regenerate this file with the current version of nanopb generator.
|
||||
#endif
|
||||
|
||||
|
||||
/* Struct definitions */
|
||||
typedef struct _privacy_context_external_ExternalPrivacyContext {
|
||||
bool has_prequest;
|
||||
privacy_context_external_ExternalPRequestContext prequest;
|
||||
/* @@protoc_insertion_point(struct:privacy_context_external_ExternalPrivacyContext) */
|
||||
} privacy_context_external_ExternalPrivacyContext;
|
||||
|
||||
/* Default values for struct fields */
|
||||
|
||||
/* Initializer values for message structs */
|
||||
#define privacy_context_external_ExternalPrivacyContext_init_default {false, privacy_context_external_ExternalPRequestContext_init_default}
|
||||
#define privacy_context_external_ExternalPrivacyContext_init_zero {false, privacy_context_external_ExternalPRequestContext_init_zero}
|
||||
|
||||
/* Field tags (for use in manual encoding/decoding) */
|
||||
#define privacy_context_external_ExternalPrivacyContext_prequest_tag 2
|
||||
|
||||
/* Struct field encoding specification for nanopb */
|
||||
extern const pb_field_t privacy_context_external_ExternalPrivacyContext_fields[2];
|
||||
|
||||
/* Maximum encoded size of messages (where known) */
|
||||
#define privacy_context_external_ExternalPrivacyContext_size 13
|
||||
|
||||
/* Message IDs (where set with "msgid" option) */
|
||||
#ifdef PB_MSGID
|
||||
|
||||
#define EXTERNAL_PRIVACY_CONTEXT_MESSAGES \
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
/* @@protoc_insertion_point(eof) */
|
||||
|
||||
#endif
|
||||
51
Pods/GoogleDataTransport/GoogleDataTransport/GDTCCTLibrary/Public/GDTCOREvent+GDTCCTSupport.h
generated
Normal file
51
Pods/GoogleDataTransport/GoogleDataTransport/GDTCCTLibrary/Public/GDTCOREvent+GDTCCTSupport.h
generated
Normal file
@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright 2020 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCOREvent.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/** A string sets in customBytes as a key paired to @YES if current event needs to
|
||||
* populate network connection info data, @NO otherwise.
|
||||
*/
|
||||
FOUNDATION_EXPORT NSString *const GDTCCTNeedsNetworkConnectionInfo;
|
||||
|
||||
/** A string sets in customBytes as a key paired to the network connection info data
|
||||
* of current event.
|
||||
*/
|
||||
FOUNDATION_EXPORT NSString *const GDTCCTNetworkConnectionInfo;
|
||||
|
||||
/** A category that uses the customBytes property of a GDTCOREvent to store network connection info.
|
||||
*/
|
||||
@interface GDTCOREvent (GDTCCTSupport)
|
||||
|
||||
/** If YES, needs the network connection info field set during prioritization.
|
||||
* @note Uses the GDTCOREvent customBytes property.
|
||||
*/
|
||||
@property(nonatomic) BOOL needsNetworkConnectionInfoPopulated;
|
||||
|
||||
/** The network connection info as collected at the time of the event.
|
||||
* @note Uses the GDTCOREvent customBytes property.
|
||||
*/
|
||||
@property(nullable, nonatomic) NSData *networkConnectionInfoData;
|
||||
|
||||
/** Code that identifies the event to be sent to the CCT backend.
|
||||
*/
|
||||
@property(nullable, nonatomic) NSNumber *eventCode;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
36
Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORAssert.m
generated
Normal file
36
Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORAssert.m
generated
Normal file
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright 2019 Google
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Internal/GDTCORAssert.h"
|
||||
|
||||
GDTCORAssertionBlock GDTCORAssertionBlockToRunInstead(void) {
|
||||
// This class is only compiled in by unit tests, and this should fail quickly in optimized builds.
|
||||
Class GDTCORAssertClass = NSClassFromString(@"GDTCORAssertHelper");
|
||||
if (__builtin_expect(!!GDTCORAssertClass, 0)) {
|
||||
SEL assertionBlockSEL = NSSelectorFromString(@"assertionBlock");
|
||||
if (assertionBlockSEL) {
|
||||
IMP assertionBlockIMP = [GDTCORAssertClass methodForSelector:assertionBlockSEL];
|
||||
if (assertionBlockIMP) {
|
||||
GDTCORAssertionBlock assertionBlock = ((GDTCORAssertionBlock(*)(id, SEL))assertionBlockIMP)(
|
||||
GDTCORAssertClass, assertionBlockSEL);
|
||||
if (assertionBlock) {
|
||||
return assertionBlock;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
174
Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORClock.m
generated
Normal file
174
Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORClock.m
generated
Normal file
@ -0,0 +1,174 @@
|
||||
/*
|
||||
* Copyright 2018 Google
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORClock.h"
|
||||
|
||||
#import <sys/sysctl.h>
|
||||
|
||||
// Using a monotonic clock is necessary because CFAbsoluteTimeGetCurrent(), NSDate, and related all
|
||||
// are subject to drift. That it to say, multiple consecutive calls do not always result in a
|
||||
// time that is in the future. Clocks may be adjusted by the user, NTP, or any number of external
|
||||
// factors. This class attempts to determine the wall-clock time at the time of the event by
|
||||
// capturing the kernel start and time since boot to determine a wallclock time in UTC.
|
||||
//
|
||||
// Timezone offsets at the time of a snapshot are also captured in order to provide local-time
|
||||
// details. Other classes in this library depend on comparing times at some time in the future to
|
||||
// a time captured in the past, and this class needs to provide a mechanism to do that.
|
||||
//
|
||||
// TL;DR: This class attempts to accomplish two things: 1. Provide accurate event times. 2. Provide
|
||||
// a monotonic clock mechanism to accurately check if some clock snapshot was before or after
|
||||
// by using a shared reference point (kernel boot time).
|
||||
//
|
||||
// Note: Much of the mach time stuff doesn't work properly in the simulator. So this class can be
|
||||
// difficult to unit test.
|
||||
|
||||
/** Returns the kernel boottime property from sysctl.
|
||||
*
|
||||
* @return The KERN_BOOTTIME property from sysctl, in nanoseconds.
|
||||
*/
|
||||
static int64_t KernelBootTimeInNanoseconds(void) {
|
||||
// Caching the result is not possible because clock drift would not be accounted for.
|
||||
struct timeval boottime;
|
||||
int mib[2] = {CTL_KERN, KERN_BOOTTIME};
|
||||
size_t size = sizeof(boottime);
|
||||
int rc = sysctl(mib, 2, &boottime, &size, NULL, 0);
|
||||
if (rc != 0) {
|
||||
return 0;
|
||||
}
|
||||
return (int64_t)boottime.tv_sec * NSEC_PER_SEC + (int64_t)boottime.tv_usec * NSEC_PER_USEC;
|
||||
}
|
||||
|
||||
/** Returns value of gettimeofday, in nanoseconds.
|
||||
*
|
||||
* @return The value of gettimeofday, in nanoseconds.
|
||||
*/
|
||||
static int64_t UptimeInNanoseconds(void) {
|
||||
int64_t before_now_nsec;
|
||||
int64_t after_now_nsec;
|
||||
struct timeval now;
|
||||
|
||||
before_now_nsec = KernelBootTimeInNanoseconds();
|
||||
// Addresses a race condition in which the system time has updated, but the boottime has not.
|
||||
do {
|
||||
gettimeofday(&now, NULL);
|
||||
after_now_nsec = KernelBootTimeInNanoseconds();
|
||||
} while (after_now_nsec != before_now_nsec);
|
||||
return (int64_t)now.tv_sec * NSEC_PER_SEC + (int64_t)now.tv_usec * NSEC_PER_USEC -
|
||||
before_now_nsec;
|
||||
}
|
||||
|
||||
// TODO: Consider adding a 'trustedTime' property that can be populated by the response from a BE.
|
||||
@implementation GDTCORClock
|
||||
|
||||
- (instancetype)init {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_kernelBootTimeNanoseconds = KernelBootTimeInNanoseconds();
|
||||
_uptimeNanoseconds = UptimeInNanoseconds();
|
||||
_timeMillis =
|
||||
(int64_t)((CFAbsoluteTimeGetCurrent() + kCFAbsoluteTimeIntervalSince1970) * NSEC_PER_USEC);
|
||||
_timezoneOffsetSeconds = [[NSTimeZone systemTimeZone] secondsFromGMT];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
+ (GDTCORClock *)snapshot {
|
||||
return [[GDTCORClock alloc] init];
|
||||
}
|
||||
|
||||
+ (instancetype)clockSnapshotInTheFuture:(uint64_t)millisInTheFuture {
|
||||
GDTCORClock *snapshot = [self snapshot];
|
||||
snapshot->_timeMillis += millisInTheFuture;
|
||||
return snapshot;
|
||||
}
|
||||
|
||||
- (BOOL)isAfter:(GDTCORClock *)otherClock {
|
||||
// These clocks are trivially comparable when they share a kernel boot time.
|
||||
if (_kernelBootTimeNanoseconds == otherClock->_kernelBootTimeNanoseconds) {
|
||||
int64_t timeDiff = (_timeMillis + _timezoneOffsetSeconds) -
|
||||
(otherClock->_timeMillis + otherClock->_timezoneOffsetSeconds);
|
||||
return timeDiff > 0;
|
||||
} else {
|
||||
int64_t kernelBootTimeDiff =
|
||||
otherClock->_kernelBootTimeNanoseconds - _kernelBootTimeNanoseconds;
|
||||
// This isn't a great solution, but essentially, if the other clock's boot time is 'later', NO
|
||||
// is returned. This can be altered by changing the system time and rebooting.
|
||||
return kernelBootTimeDiff < 0 ? YES : NO;
|
||||
}
|
||||
}
|
||||
|
||||
- (int64_t)uptimeMilliseconds {
|
||||
return self.uptimeNanoseconds / NSEC_PER_MSEC;
|
||||
}
|
||||
|
||||
- (NSUInteger)hash {
|
||||
return [@(_kernelBootTimeNanoseconds) hash] ^ [@(_uptimeNanoseconds) hash] ^
|
||||
[@(_timeMillis) hash] ^ [@(_timezoneOffsetSeconds) hash];
|
||||
}
|
||||
|
||||
- (BOOL)isEqual:(id)object {
|
||||
return [self hash] == [object hash];
|
||||
}
|
||||
|
||||
#pragma mark - NSSecureCoding
|
||||
|
||||
/** NSKeyedCoder key for timeMillis property. */
|
||||
static NSString *const kGDTCORClockTimeMillisKey = @"GDTCORClockTimeMillis";
|
||||
|
||||
/** NSKeyedCoder key for timezoneOffsetMillis property. */
|
||||
static NSString *const kGDTCORClockTimezoneOffsetSeconds = @"GDTCORClockTimezoneOffsetSeconds";
|
||||
|
||||
/** NSKeyedCoder key for _kernelBootTime ivar. */
|
||||
static NSString *const kGDTCORClockKernelBootTime = @"GDTCORClockKernelBootTime";
|
||||
|
||||
/** NSKeyedCoder key for _uptimeNanoseconds ivar. */
|
||||
static NSString *const kGDTCORClockUptime = @"GDTCORClockUptime";
|
||||
|
||||
+ (BOOL)supportsSecureCoding {
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (instancetype)initWithCoder:(NSCoder *)aDecoder {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
// TODO: If the kernelBootTimeNanoseconds is more recent, we need to change the kernel boot time
|
||||
// and uptimeMillis ivars
|
||||
_timeMillis = [aDecoder decodeInt64ForKey:kGDTCORClockTimeMillisKey];
|
||||
_timezoneOffsetSeconds = [aDecoder decodeInt64ForKey:kGDTCORClockTimezoneOffsetSeconds];
|
||||
_kernelBootTimeNanoseconds = [aDecoder decodeInt64ForKey:kGDTCORClockKernelBootTime];
|
||||
_uptimeNanoseconds = [aDecoder decodeInt64ForKey:kGDTCORClockUptime];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)encodeWithCoder:(NSCoder *)aCoder {
|
||||
[aCoder encodeInt64:_timeMillis forKey:kGDTCORClockTimeMillisKey];
|
||||
[aCoder encodeInt64:_timezoneOffsetSeconds forKey:kGDTCORClockTimezoneOffsetSeconds];
|
||||
[aCoder encodeInt64:_kernelBootTimeNanoseconds forKey:kGDTCORClockKernelBootTime];
|
||||
[aCoder encodeInt64:_uptimeNanoseconds forKey:kGDTCORClockUptime];
|
||||
}
|
||||
|
||||
#pragma mark - Deprecated properties
|
||||
|
||||
- (int64_t)kernelBootTime {
|
||||
return self.kernelBootTimeNanoseconds;
|
||||
}
|
||||
|
||||
- (int64_t)uptime {
|
||||
return self.uptimeNanoseconds;
|
||||
}
|
||||
|
||||
@end
|
||||
55
Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORConsoleLogger.m
generated
Normal file
55
Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORConsoleLogger.m
generated
Normal file
@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright 2018 Google
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORConsoleLogger.h"
|
||||
|
||||
volatile NSInteger GDTCORConsoleLoggerLoggingLevel = GDTCORLoggingLevelErrors;
|
||||
|
||||
/** The console logger prefix. */
|
||||
static NSString *kGDTCORConsoleLogger = @"[GoogleDataTransport]";
|
||||
|
||||
NSString *GDTCORMessageCodeEnumToString(GDTCORMessageCode code) {
|
||||
return [[NSString alloc] initWithFormat:@"I-GDTCOR%06ld", (long)code];
|
||||
}
|
||||
|
||||
void GDTCORLog(GDTCORMessageCode code, GDTCORLoggingLevel logLevel, NSString *format, ...) {
|
||||
// Don't log anything in not debug builds.
|
||||
#if !NDEBUG
|
||||
if (logLevel >= GDTCORConsoleLoggerLoggingLevel) {
|
||||
NSString *logFormat = [NSString stringWithFormat:@"%@[%@] %@", kGDTCORConsoleLogger,
|
||||
GDTCORMessageCodeEnumToString(code), format];
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
NSLogv(logFormat, args);
|
||||
va_end(args);
|
||||
}
|
||||
#endif // !NDEBUG
|
||||
}
|
||||
|
||||
void GDTCORLogAssert(
|
||||
BOOL wasFatal, NSString *_Nonnull file, NSInteger line, NSString *_Nullable format, ...) {
|
||||
// Don't log anything in not debug builds.
|
||||
#if !NDEBUG
|
||||
GDTCORMessageCode code = wasFatal ? GDTCORMCEFatalAssertion : GDTCORMCEGeneralError;
|
||||
NSString *logFormat =
|
||||
[NSString stringWithFormat:@"%@[%@] (%@:%ld) : %@", kGDTCORConsoleLogger,
|
||||
GDTCORMessageCodeEnumToString(code), file, (long)line, format];
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
NSLogv(logFormat, args);
|
||||
va_end(args);
|
||||
#endif // !NDEBUG
|
||||
}
|
||||
101
Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORDirectorySizeTracker.m
generated
Normal file
101
Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORDirectorySizeTracker.m
generated
Normal file
@ -0,0 +1,101 @@
|
||||
/*
|
||||
* Copyright 2020 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Internal/GDTCORDirectorySizeTracker.h"
|
||||
|
||||
@interface GDTCORDirectorySizeTracker ()
|
||||
|
||||
/** The observed directory path. */
|
||||
@property(nonatomic, readonly) NSString *directoryPath;
|
||||
|
||||
/** The cached content size of the observed directory. */
|
||||
@property(nonatomic, nullable) NSNumber *cachedSizeBytes;
|
||||
|
||||
@end
|
||||
|
||||
@implementation GDTCORDirectorySizeTracker
|
||||
|
||||
- (instancetype)initWithDirectoryPath:(NSString *)path {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_directoryPath = path;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (GDTCORStorageSizeBytes)directoryContentSize {
|
||||
if (self.cachedSizeBytes == nil) {
|
||||
self.cachedSizeBytes = @([self calculateDirectoryContentSize]);
|
||||
}
|
||||
|
||||
return self.cachedSizeBytes.unsignedLongLongValue;
|
||||
}
|
||||
|
||||
- (void)fileWasAddedAtPath:(NSString *)path withSize:(GDTCORStorageSizeBytes)fileSize {
|
||||
if (![path hasPrefix:self.directoryPath]) {
|
||||
// Ignore because the file is not inside the directory.
|
||||
return;
|
||||
}
|
||||
|
||||
self.cachedSizeBytes = @([self directoryContentSize] + fileSize);
|
||||
}
|
||||
|
||||
- (void)fileWasRemovedAtPath:(NSString *)path withSize:(GDTCORStorageSizeBytes)fileSize {
|
||||
if (![path hasPrefix:self.directoryPath]) {
|
||||
// Ignore because the file is not inside the directory.
|
||||
return;
|
||||
}
|
||||
|
||||
self.cachedSizeBytes = @([self directoryContentSize] - fileSize);
|
||||
}
|
||||
|
||||
- (void)resetCachedSize {
|
||||
self.cachedSizeBytes = nil;
|
||||
}
|
||||
|
||||
- (GDTCORStorageSizeBytes)calculateDirectoryContentSize {
|
||||
NSArray *prefetchedProperties = @[ NSURLIsRegularFileKey, NSURLFileSizeKey ];
|
||||
uint64_t totalBytes = 0;
|
||||
NSURL *directoryURL = [NSURL fileURLWithPath:self.directoryPath];
|
||||
|
||||
NSDirectoryEnumerator *enumerator = [[NSFileManager defaultManager]
|
||||
enumeratorAtURL:directoryURL
|
||||
includingPropertiesForKeys:prefetchedProperties
|
||||
options:NSDirectoryEnumerationSkipsHiddenFiles
|
||||
errorHandler:^BOOL(NSURL *_Nonnull url, NSError *_Nonnull error) {
|
||||
return YES;
|
||||
}];
|
||||
|
||||
for (NSURL *fileURL in enumerator) {
|
||||
@autoreleasepool {
|
||||
NSNumber *isRegularFile;
|
||||
[fileURL getResourceValue:&isRegularFile forKey:NSURLIsRegularFileKey error:nil];
|
||||
if (isRegularFile.boolValue) {
|
||||
totalBytes += [self fileSizeAtURL:fileURL];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return totalBytes;
|
||||
}
|
||||
|
||||
- (GDTCORStorageSizeBytes)fileSizeAtURL:(NSURL *)fileURL {
|
||||
NSNumber *fileSize;
|
||||
[fileURL getResourceValue:&fileSize forKey:NSURLFileSizeKey error:nil];
|
||||
return fileSize.unsignedLongLongValue;
|
||||
}
|
||||
|
||||
@end
|
||||
92
Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCOREndpoints.m
generated
Normal file
92
Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCOREndpoints.m
generated
Normal file
@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright 2020 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCOREndpoints.h"
|
||||
|
||||
static NSString *const kINTServerURL =
|
||||
@"https://dummyapiverylong-dummy.google.com/dummy/api/very/long";
|
||||
|
||||
@implementation GDTCOREndpoints
|
||||
|
||||
+ (NSDictionary<NSNumber *, NSURL *> *)uploadURLs {
|
||||
// These strings should be interleaved to construct the real URL. This is just to (hopefully)
|
||||
// fool github URL scanning bots.
|
||||
static NSURL *CCTServerURL;
|
||||
static dispatch_once_t CCTOnceToken;
|
||||
dispatch_once(&CCTOnceToken, ^{
|
||||
const char *p1 = "hts/frbslgiggolai.o/0clgbth";
|
||||
const char *p2 = "tp:/ieaeogn.ogepscmvc/o/ac";
|
||||
const char URL[54] = {p1[0], p2[0], p1[1], p2[1], p1[2], p2[2], p1[3], p2[3], p1[4],
|
||||
p2[4], p1[5], p2[5], p1[6], p2[6], p1[7], p2[7], p1[8], p2[8],
|
||||
p1[9], p2[9], p1[10], p2[10], p1[11], p2[11], p1[12], p2[12], p1[13],
|
||||
p2[13], p1[14], p2[14], p1[15], p2[15], p1[16], p2[16], p1[17], p2[17],
|
||||
p1[18], p2[18], p1[19], p2[19], p1[20], p2[20], p1[21], p2[21], p1[22],
|
||||
p2[22], p1[23], p2[23], p1[24], p2[24], p1[25], p2[25], p1[26], '\0'};
|
||||
CCTServerURL = [NSURL URLWithString:[NSString stringWithUTF8String:URL]];
|
||||
});
|
||||
|
||||
static NSURL *FLLServerURL;
|
||||
static dispatch_once_t FLLOnceToken;
|
||||
dispatch_once(&FLLOnceToken, ^{
|
||||
const char *p1 = "hts/frbslgigp.ogepscmv/ieo/eaybtho";
|
||||
const char *p2 = "tp:/ieaeogn-agolai.o/1frlglgc/aclg";
|
||||
const char URL[69] = {p1[0], p2[0], p1[1], p2[1], p1[2], p2[2], p1[3], p2[3], p1[4],
|
||||
p2[4], p1[5], p2[5], p1[6], p2[6], p1[7], p2[7], p1[8], p2[8],
|
||||
p1[9], p2[9], p1[10], p2[10], p1[11], p2[11], p1[12], p2[12], p1[13],
|
||||
p2[13], p1[14], p2[14], p1[15], p2[15], p1[16], p2[16], p1[17], p2[17],
|
||||
p1[18], p2[18], p1[19], p2[19], p1[20], p2[20], p1[21], p2[21], p1[22],
|
||||
p2[22], p1[23], p2[23], p1[24], p2[24], p1[25], p2[25], p1[26], p2[26],
|
||||
p1[27], p2[27], p1[28], p2[28], p1[29], p2[29], p1[30], p2[30], p1[31],
|
||||
p2[31], p1[32], p2[32], p1[33], p2[33], '\0'};
|
||||
FLLServerURL = [NSURL URLWithString:[NSString stringWithUTF8String:URL]];
|
||||
});
|
||||
|
||||
static NSURL *CSHServerURL;
|
||||
static dispatch_once_t CSHOnceToken;
|
||||
dispatch_once(&CSHOnceToken, ^{
|
||||
// These strings should be interleaved to construct the real URL. This is just to (hopefully)
|
||||
// fool github URL scanning bots.
|
||||
const char *p1 = "hts/cahyiseot-agolai.o/1frlglgc/aclg";
|
||||
const char *p2 = "tp:/rsltcrprsp.ogepscmv/ieo/eaybtho";
|
||||
const char URL[72] = {p1[0], p2[0], p1[1], p2[1], p1[2], p2[2], p1[3], p2[3], p1[4],
|
||||
p2[4], p1[5], p2[5], p1[6], p2[6], p1[7], p2[7], p1[8], p2[8],
|
||||
p1[9], p2[9], p1[10], p2[10], p1[11], p2[11], p1[12], p2[12], p1[13],
|
||||
p2[13], p1[14], p2[14], p1[15], p2[15], p1[16], p2[16], p1[17], p2[17],
|
||||
p1[18], p2[18], p1[19], p2[19], p1[20], p2[20], p1[21], p2[21], p1[22],
|
||||
p2[22], p1[23], p2[23], p1[24], p2[24], p1[25], p2[25], p1[26], p2[26],
|
||||
p1[27], p2[27], p1[28], p2[28], p1[29], p2[29], p1[30], p2[30], p1[31],
|
||||
p2[31], p1[32], p2[32], p1[33], p2[33], p1[34], p2[34], p1[35], '\0'};
|
||||
CSHServerURL = [NSURL URLWithString:[NSString stringWithUTF8String:URL]];
|
||||
});
|
||||
static NSDictionary<NSNumber *, NSURL *> *uploadURLs;
|
||||
static dispatch_once_t URLOnceToken;
|
||||
dispatch_once(&URLOnceToken, ^{
|
||||
uploadURLs = @{
|
||||
@(kGDTCORTargetCCT) : CCTServerURL,
|
||||
@(kGDTCORTargetFLL) : FLLServerURL,
|
||||
@(kGDTCORTargetCSH) : CSHServerURL,
|
||||
@(kGDTCORTargetINT) : [NSURL URLWithString:kINTServerURL]
|
||||
};
|
||||
});
|
||||
return uploadURLs;
|
||||
}
|
||||
|
||||
+ (nullable NSURL *)uploadURLForTarget:(GDTCORTarget)target {
|
||||
NSDictionary<NSNumber *, NSURL *> *URLs = [self uploadURLs];
|
||||
return [URLs objectForKey:@(target)];
|
||||
}
|
||||
|
||||
@end
|
||||
170
Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCOREvent.m
generated
Normal file
170
Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCOREvent.m
generated
Normal file
@ -0,0 +1,170 @@
|
||||
/*
|
||||
* Copyright 2018 Google
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCOREvent.h"
|
||||
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Internal/GDTCORAssert.h"
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Internal/GDTCORPlatform.h"
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Internal/GDTCORStorageProtocol.h"
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORClock.h"
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORConsoleLogger.h"
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORProductData.h"
|
||||
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Private/GDTCOREvent_Private.h"
|
||||
|
||||
@implementation GDTCOREvent
|
||||
|
||||
+ (NSString *)nextEventID {
|
||||
// Replace special non-alphanumeric characters to avoid potential conflicts with storage logic.
|
||||
return [[NSUUID UUID].UUIDString stringByReplacingOccurrencesOfString:@"-" withString:@""];
|
||||
}
|
||||
|
||||
- (nullable instancetype)initWithMappingID:(NSString *)mappingID
|
||||
productData:(nullable GDTCORProductData *)productData
|
||||
target:(GDTCORTarget)target {
|
||||
GDTCORAssert(mappingID.length > 0, @"Please give a valid mapping ID");
|
||||
GDTCORAssert(target > 0, @"A target cannot be negative or 0");
|
||||
if (mappingID.length == 0 || target <= 0) {
|
||||
return nil;
|
||||
}
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_eventID = [GDTCOREvent nextEventID];
|
||||
_mappingID = mappingID;
|
||||
_productData = productData;
|
||||
_target = target;
|
||||
_qosTier = GDTCOREventQosDefault;
|
||||
_expirationDate = [NSDate dateWithTimeIntervalSinceNow:604800]; // 7 days.
|
||||
|
||||
GDTCORLogDebug(@"Event %@ created. ID:%@ mappingID: %@ target:%ld", self, _eventID, mappingID,
|
||||
(long)target);
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (nullable instancetype)initWithMappingID:(NSString *)mappingID target:(GDTCORTarget)target {
|
||||
return [self initWithMappingID:mappingID productData:nil target:target];
|
||||
}
|
||||
|
||||
- (instancetype)copy {
|
||||
GDTCOREvent *copy = [[GDTCOREvent alloc] initWithMappingID:_mappingID
|
||||
productData:_productData
|
||||
target:_target];
|
||||
copy->_eventID = _eventID;
|
||||
copy.dataObject = _dataObject;
|
||||
copy.qosTier = _qosTier;
|
||||
copy.clockSnapshot = _clockSnapshot;
|
||||
copy.customBytes = _customBytes;
|
||||
GDTCORLogDebug(@"Copying event %@ to event %@", self, copy);
|
||||
return copy;
|
||||
}
|
||||
|
||||
- (NSUInteger)hash {
|
||||
// This loses some precision, but it's probably fine.
|
||||
NSUInteger eventIDHash = [_eventID hash];
|
||||
NSUInteger mappingIDHash = [_mappingID hash];
|
||||
NSUInteger productDataHash = [_productData hash];
|
||||
NSUInteger timeHash = [_clockSnapshot hash];
|
||||
NSInteger serializedBytesHash = [_serializedDataObjectBytes hash];
|
||||
|
||||
return eventIDHash ^ mappingIDHash ^ productDataHash ^ _target ^ _qosTier ^ timeHash ^
|
||||
serializedBytesHash;
|
||||
}
|
||||
|
||||
- (BOOL)isEqual:(id)object {
|
||||
return [self hash] == [object hash];
|
||||
}
|
||||
|
||||
#pragma mark - Property overrides
|
||||
|
||||
- (void)setDataObject:(id<GDTCOREventDataObject>)dataObject {
|
||||
// If you're looking here because of a performance issue in -transportBytes slowing the assignment
|
||||
// of -dataObject, one way to address this is to add a queue to this class,
|
||||
// dispatch_(barrier_ if concurrent)async here, and implement the getter with a dispatch_sync.
|
||||
if (dataObject != _dataObject) {
|
||||
_dataObject = dataObject;
|
||||
}
|
||||
self->_serializedDataObjectBytes = [dataObject transportBytes];
|
||||
}
|
||||
|
||||
#pragma mark - NSSecureCoding and NSCoding Protocols
|
||||
|
||||
/** NSCoding key for eventID property. */
|
||||
static NSString *kEventIDKey = @"GDTCOREventEventIDKey";
|
||||
|
||||
/** NSCoding key for mappingID property. */
|
||||
static NSString *kMappingIDKey = @"GDTCOREventMappingIDKey";
|
||||
|
||||
/** NSCoding key for target property. */
|
||||
static NSString *kTargetKey = @"GDTCOREventTargetKey";
|
||||
|
||||
/** NSCoding key for qosTier property. */
|
||||
static NSString *kQoSTierKey = @"GDTCOREventQoSTierKey";
|
||||
|
||||
/** NSCoding key for clockSnapshot property. */
|
||||
static NSString *kClockSnapshotKey = @"GDTCOREventClockSnapshotKey";
|
||||
|
||||
/** NSCoding key for expirationDate property. */
|
||||
static NSString *kExpirationDateKey = @"GDTCOREventExpirationDateKey";
|
||||
|
||||
/** NSCoding key for serializedDataObjectBytes property. */
|
||||
static NSString *kSerializedDataObjectBytes = @"GDTCOREventSerializedDataObjectBytesKey";
|
||||
|
||||
/** NSCoding key for customData property. */
|
||||
static NSString *kCustomDataKey = @"GDTCOREventCustomDataKey";
|
||||
|
||||
/** NSCoding key for productData property. */
|
||||
static NSString *kProductDataKey = @"GDTCOREventProductDataKey";
|
||||
|
||||
+ (BOOL)supportsSecureCoding {
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (id)initWithCoder:(NSCoder *)aDecoder {
|
||||
self = [self init];
|
||||
if (self) {
|
||||
_mappingID = [aDecoder decodeObjectOfClass:[NSString class] forKey:kMappingIDKey];
|
||||
_productData = [aDecoder decodeObjectOfClass:[GDTCORProductData class] forKey:kProductDataKey];
|
||||
_target = [aDecoder decodeIntegerForKey:kTargetKey];
|
||||
_eventID = [aDecoder decodeObjectOfClass:[NSString class] forKey:kEventIDKey]
|
||||
?: [GDTCOREvent nextEventID];
|
||||
_qosTier = [aDecoder decodeIntegerForKey:kQoSTierKey];
|
||||
_clockSnapshot = [aDecoder decodeObjectOfClass:[GDTCORClock class] forKey:kClockSnapshotKey];
|
||||
_customBytes = [aDecoder decodeObjectOfClass:[NSData class] forKey:kCustomDataKey];
|
||||
_expirationDate = [aDecoder decodeObjectOfClass:[NSDate class] forKey:kExpirationDateKey];
|
||||
_serializedDataObjectBytes = [aDecoder decodeObjectOfClass:[NSData class]
|
||||
forKey:kSerializedDataObjectBytes];
|
||||
if (!_serializedDataObjectBytes) {
|
||||
return nil;
|
||||
}
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)encodeWithCoder:(NSCoder *)aCoder {
|
||||
[aCoder encodeObject:_eventID forKey:kEventIDKey];
|
||||
[aCoder encodeObject:_mappingID forKey:kMappingIDKey];
|
||||
[aCoder encodeObject:_productData forKey:kProductDataKey];
|
||||
[aCoder encodeInteger:_target forKey:kTargetKey];
|
||||
[aCoder encodeInteger:_qosTier forKey:kQoSTierKey];
|
||||
[aCoder encodeObject:_clockSnapshot forKey:kClockSnapshotKey];
|
||||
[aCoder encodeObject:_customBytes forKey:kCustomDataKey];
|
||||
[aCoder encodeObject:_expirationDate forKey:kExpirationDateKey];
|
||||
[aCoder encodeObject:self.serializedDataObjectBytes forKey:kSerializedDataObjectBytes];
|
||||
}
|
||||
|
||||
@end
|
||||
161
Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORFlatFileStorage+Promises.m
generated
Normal file
161
Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORFlatFileStorage+Promises.m
generated
Normal file
@ -0,0 +1,161 @@
|
||||
/*
|
||||
* Copyright 2020 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Private/GDTCORFlatFileStorage+Promises.h"
|
||||
|
||||
#if __has_include(<FBLPromises/FBLPromises.h>)
|
||||
#import <FBLPromises/FBLPromises.h>
|
||||
#else
|
||||
#import "FBLPromises.h"
|
||||
#endif
|
||||
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Internal/GDTCORPlatform.h"
|
||||
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Private/GDTCORMetricsMetadata.h"
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Private/GDTCORStorageMetadata.h"
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Private/GDTCORUploadBatch.h"
|
||||
|
||||
@implementation GDTCORFlatFileStorage (Promises)
|
||||
|
||||
- (FBLPromise<NSSet<NSNumber *> *> *)batchIDsForTarget:(GDTCORTarget)target {
|
||||
return [FBLPromise onQueue:self.storageQueue
|
||||
wrapObjectCompletion:^(FBLPromiseObjectCompletion _Nonnull handler) {
|
||||
[self batchIDsForTarget:target onComplete:handler];
|
||||
}];
|
||||
}
|
||||
|
||||
- (FBLPromise<NSNull *> *)removeBatchWithID:(NSNumber *)batchID deleteEvents:(BOOL)deleteEvents {
|
||||
return [FBLPromise onQueue:self.storageQueue
|
||||
wrapCompletion:^(FBLPromiseCompletion _Nonnull handler) {
|
||||
[self removeBatchWithID:batchID deleteEvents:deleteEvents onComplete:handler];
|
||||
}];
|
||||
}
|
||||
|
||||
- (FBLPromise<NSNull *> *)removeBatchesWithIDs:(NSSet<NSNumber *> *)batchIDs
|
||||
deleteEvents:(BOOL)deleteEvents {
|
||||
NSMutableArray<FBLPromise *> *removeBatchPromises =
|
||||
[NSMutableArray arrayWithCapacity:batchIDs.count];
|
||||
for (NSNumber *batchID in batchIDs) {
|
||||
[removeBatchPromises addObject:[self removeBatchWithID:batchID deleteEvents:deleteEvents]];
|
||||
}
|
||||
|
||||
return [FBLPromise onQueue:self.storageQueue all:[removeBatchPromises copy]].thenOn(
|
||||
self.storageQueue, ^id(id result) {
|
||||
return [FBLPromise resolvedWith:[NSNull null]];
|
||||
});
|
||||
}
|
||||
|
||||
- (FBLPromise<NSNull *> *)removeAllBatchesForTarget:(GDTCORTarget)target
|
||||
deleteEvents:(BOOL)deleteEvents {
|
||||
return
|
||||
[self batchIDsForTarget:target].thenOn(self.storageQueue, ^id(NSSet<NSNumber *> *batchIDs) {
|
||||
if (batchIDs.count == 0) {
|
||||
return [FBLPromise resolvedWith:[NSNull null]];
|
||||
} else {
|
||||
return [self removeBatchesWithIDs:batchIDs deleteEvents:NO];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
- (FBLPromise<NSNumber *> *)hasEventsForTarget:(GDTCORTarget)target {
|
||||
return [FBLPromise onQueue:self.storageQueue
|
||||
wrapBoolCompletion:^(FBLPromiseBoolCompletion _Nonnull handler) {
|
||||
[self hasEventsForTarget:target onComplete:handler];
|
||||
}];
|
||||
}
|
||||
|
||||
- (FBLPromise<GDTCORUploadBatch *> *)batchWithEventSelector:
|
||||
(GDTCORStorageEventSelector *)eventSelector
|
||||
batchExpiration:(NSDate *)expiration {
|
||||
return [FBLPromise
|
||||
onQueue:self.storageQueue
|
||||
async:^(FBLPromiseFulfillBlock _Nonnull fulfill, FBLPromiseRejectBlock _Nonnull reject) {
|
||||
[self batchWithEventSelector:eventSelector
|
||||
batchExpiration:expiration
|
||||
onComplete:^(NSNumber *_Nullable newBatchID,
|
||||
NSSet<GDTCOREvent *> *_Nullable batchEvents) {
|
||||
if (newBatchID == nil || batchEvents == nil) {
|
||||
reject([self genericRejectedPromiseErrorWithReason:
|
||||
@"There are no events for the selector."]);
|
||||
} else {
|
||||
fulfill([[GDTCORUploadBatch alloc] initWithBatchID:newBatchID
|
||||
events:batchEvents]);
|
||||
}
|
||||
}];
|
||||
}];
|
||||
}
|
||||
|
||||
- (FBLPromise<NSNull *> *)fetchAndUpdateMetricsWithHandler:
|
||||
(GDTCORMetricsMetadata * (^)(GDTCORMetricsMetadata *_Nullable fetchedMetadata,
|
||||
NSError *_Nullable fetchError))handler {
|
||||
return FBLPromise.doOn(self.storageQueue, ^id {
|
||||
// Fetch the stored metrics metadata.
|
||||
NSError *decodeError;
|
||||
NSString *metricsMetadataPath =
|
||||
[[[self class] libraryDataStoragePath] stringByAppendingPathComponent:@"metrics_metadata"];
|
||||
GDTCORMetricsMetadata *decodedMetadata = (GDTCORMetricsMetadata *)GDTCORDecodeArchiveAtPath(
|
||||
GDTCORMetricsMetadata.class, metricsMetadataPath, &decodeError);
|
||||
|
||||
// Update the metadata using the retrieved metadata.
|
||||
GDTCORMetricsMetadata *updatedMetadata = handler(decodedMetadata, decodeError);
|
||||
if (updatedMetadata == nil) {
|
||||
// `nil` metadata is not expected and will be a no-op.
|
||||
return nil;
|
||||
}
|
||||
|
||||
if (![updatedMetadata isEqual:decodedMetadata]) {
|
||||
// The metadata was updated so it needs to be saved.
|
||||
// - Encode the updated metadata.
|
||||
NSError *encodeError;
|
||||
NSData *encodedMetadata = GDTCOREncodeArchive(updatedMetadata, nil, &encodeError);
|
||||
if (encodeError) {
|
||||
return encodeError;
|
||||
}
|
||||
|
||||
// - Write the encoded metadata to disk.
|
||||
NSError *writeError;
|
||||
BOOL writeResult = GDTCORWriteDataToFile(encodedMetadata, metricsMetadataPath, &writeError);
|
||||
if (writeResult == NO || writeError) {
|
||||
return writeError;
|
||||
}
|
||||
}
|
||||
|
||||
return nil;
|
||||
});
|
||||
}
|
||||
|
||||
- (FBLPromise<GDTCORStorageMetadata *> *)fetchStorageMetadata {
|
||||
return FBLPromise.asyncOn(self.storageQueue, ^(FBLPromiseFulfillBlock _Nonnull fulfill,
|
||||
FBLPromiseRejectBlock _Nonnull reject) {
|
||||
[self storageSizeWithCallback:^(GDTCORStorageSizeBytes storageSize) {
|
||||
fulfill([GDTCORStorageMetadata metadataWithCurrentCacheSize:storageSize
|
||||
maxCacheSize:kGDTCORFlatFileStorageSizeLimit]);
|
||||
}];
|
||||
});
|
||||
}
|
||||
|
||||
// TODO: Move to a separate class/extension when needed in more places.
|
||||
- (NSError *)genericRejectedPromiseErrorWithReason:(NSString *)reason {
|
||||
return [NSError errorWithDomain:@"GDTCORFlatFileStorage"
|
||||
code:-1
|
||||
userInfo:@{NSLocalizedFailureReasonErrorKey : reason}];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
/// Stub used to force the linker to include the categories in this file.
|
||||
void GDTCORInclude_GDTCORLogSourceMetrics_Internal_Category(void) {
|
||||
}
|
||||
849
Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORFlatFileStorage.m
generated
Normal file
849
Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORFlatFileStorage.m
generated
Normal file
@ -0,0 +1,849 @@
|
||||
/*
|
||||
* Copyright 2018 Google
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Private/GDTCORFlatFileStorage.h"
|
||||
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Internal/GDTCORAssert.h"
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Internal/GDTCORLifecycle.h"
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Internal/GDTCORPlatform.h"
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Internal/GDTCORStorageEventSelector.h"
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORConsoleLogger.h"
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCOREvent.h"
|
||||
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Private/GDTCOREvent_Private.h"
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Private/GDTCORRegistrar_Private.h"
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Private/GDTCORUploadCoordinator.h"
|
||||
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Internal/GDTCORDirectorySizeTracker.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/** A library data key this class uses to track batchIDs. */
|
||||
static NSString *const gBatchIDCounterKey = @"GDTCORFlatFileStorageBatchIDCounter";
|
||||
|
||||
/** The separator used between metadata elements in filenames. */
|
||||
static NSString *const kMetadataSeparator = @"-";
|
||||
|
||||
NSString *const kGDTCOREventComponentsEventIDKey = @"GDTCOREventComponentsEventIDKey";
|
||||
|
||||
NSString *const kGDTCOREventComponentsQoSTierKey = @"GDTCOREventComponentsQoSTierKey";
|
||||
|
||||
NSString *const kGDTCOREventComponentsMappingIDKey = @"GDTCOREventComponentsMappingIDKey";
|
||||
|
||||
NSString *const kGDTCOREventComponentsExpirationKey = @"GDTCOREventComponentsExpirationKey";
|
||||
|
||||
NSString *const kGDTCORBatchComponentsTargetKey = @"GDTCORBatchComponentsTargetKey";
|
||||
|
||||
NSString *const kGDTCORBatchComponentsBatchIDKey = @"GDTCORBatchComponentsBatchIDKey";
|
||||
|
||||
NSString *const kGDTCORBatchComponentsExpirationKey = @"GDTCORBatchComponentsExpirationKey";
|
||||
|
||||
NSString *const GDTCORFlatFileStorageErrorDomain = @"GDTCORFlatFileStorage";
|
||||
|
||||
const uint64_t kGDTCORFlatFileStorageSizeLimit = 20 * 1000 * 1000; // 20 MB.
|
||||
|
||||
@interface GDTCORFlatFileStorage ()
|
||||
|
||||
/** An instance of the size tracker to keep track of the disk space consumed by the storage. */
|
||||
@property(nonatomic, readonly) GDTCORDirectorySizeTracker *sizeTracker;
|
||||
|
||||
@end
|
||||
|
||||
@implementation GDTCORFlatFileStorage
|
||||
|
||||
@synthesize sizeTracker = _sizeTracker;
|
||||
@synthesize delegate = _delegate;
|
||||
|
||||
+ (void)load {
|
||||
#if !NDEBUG
|
||||
[[GDTCORRegistrar sharedInstance] registerStorage:[self sharedInstance] target:kGDTCORTargetTest];
|
||||
#endif // !NDEBUG
|
||||
[[GDTCORRegistrar sharedInstance] registerStorage:[self sharedInstance] target:kGDTCORTargetCCT];
|
||||
[[GDTCORRegistrar sharedInstance] registerStorage:[self sharedInstance] target:kGDTCORTargetFLL];
|
||||
[[GDTCORRegistrar sharedInstance] registerStorage:[self sharedInstance] target:kGDTCORTargetCSH];
|
||||
[[GDTCORRegistrar sharedInstance] registerStorage:[self sharedInstance] target:kGDTCORTargetINT];
|
||||
}
|
||||
|
||||
+ (instancetype)sharedInstance {
|
||||
static GDTCORFlatFileStorage *sharedStorage;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
sharedStorage = [[GDTCORFlatFileStorage alloc] init];
|
||||
});
|
||||
return sharedStorage;
|
||||
}
|
||||
|
||||
- (instancetype)init {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_storageQueue =
|
||||
dispatch_queue_create("com.google.GDTCORFlatFileStorage", DISPATCH_QUEUE_SERIAL);
|
||||
_uploadCoordinator = [GDTCORUploadCoordinator sharedInstance];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (GDTCORDirectorySizeTracker *)sizeTracker {
|
||||
if (_sizeTracker == nil) {
|
||||
_sizeTracker =
|
||||
[[GDTCORDirectorySizeTracker alloc] initWithDirectoryPath:GDTCORRootDirectory().path];
|
||||
}
|
||||
return _sizeTracker;
|
||||
}
|
||||
|
||||
#pragma mark - GDTCORStorageProtocol
|
||||
|
||||
- (void)storeEvent:(GDTCOREvent *)event
|
||||
onComplete:(void (^_Nullable)(BOOL wasWritten, NSError *_Nullable error))completion {
|
||||
GDTCORLogDebug(@"Saving event: %@", event);
|
||||
if (event == nil || event.serializedDataObjectBytes == nil) {
|
||||
GDTCORLogDebug(@"%@", @"The event was nil, so it was not saved.");
|
||||
if (completion) {
|
||||
completion(NO, [NSError errorWithDomain:NSInternalInconsistencyException
|
||||
code:-1
|
||||
userInfo:nil]);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (!completion) {
|
||||
completion = ^(BOOL wasWritten, NSError *_Nullable error) {
|
||||
GDTCORLogDebug(@"event %@ stored. success:%@ error:%@", event, wasWritten ? @"YES" : @"NO",
|
||||
error);
|
||||
};
|
||||
}
|
||||
|
||||
__block GDTCORBackgroundIdentifier bgID = GDTCORBackgroundIdentifierInvalid;
|
||||
bgID = [[GDTCORApplication sharedApplication]
|
||||
beginBackgroundTaskWithName:@"GDTStorage"
|
||||
expirationHandler:^{
|
||||
// End the background task if it's still valid.
|
||||
[[GDTCORApplication sharedApplication] endBackgroundTask:bgID];
|
||||
bgID = GDTCORBackgroundIdentifierInvalid;
|
||||
}];
|
||||
|
||||
dispatch_async(_storageQueue, ^{
|
||||
// Check that a backend implementation is available for this target.
|
||||
GDTCORTarget target = event.target;
|
||||
NSString *filePath = [GDTCORFlatFileStorage pathForTarget:target
|
||||
eventID:event.eventID
|
||||
qosTier:@(event.qosTier)
|
||||
expirationDate:event.expirationDate
|
||||
mappingID:event.mappingID];
|
||||
NSError *error;
|
||||
NSData *encodedEvent = GDTCOREncodeArchive(event, nil, &error);
|
||||
if (error) {
|
||||
completion(NO, error);
|
||||
return;
|
||||
}
|
||||
|
||||
// Check storage size limit before storing the event.
|
||||
uint64_t resultingStorageSize = self.sizeTracker.directoryContentSize + encodedEvent.length;
|
||||
if (resultingStorageSize > kGDTCORFlatFileStorageSizeLimit) {
|
||||
NSError *error = [NSError
|
||||
errorWithDomain:GDTCORFlatFileStorageErrorDomain
|
||||
code:GDTCORFlatFileStorageErrorSizeLimitReached
|
||||
userInfo:@{
|
||||
NSLocalizedFailureReasonErrorKey : @"Storage size limit has been reached."
|
||||
}];
|
||||
if (self.delegate != nil) {
|
||||
GDTCORLogDebug(@"Delegate notified that event with mapping ID %@ was dropped.",
|
||||
event.mappingID);
|
||||
[self.delegate storage:self didDropEvent:event];
|
||||
}
|
||||
completion(NO, error);
|
||||
return;
|
||||
}
|
||||
|
||||
// Write the encoded event to the file.
|
||||
BOOL writeResult = GDTCORWriteDataToFile(encodedEvent, filePath, &error);
|
||||
if (writeResult == NO || error) {
|
||||
GDTCORLogDebug(@"Attempt to write archive failed: path:%@ error:%@", filePath, error);
|
||||
completion(NO, error);
|
||||
return;
|
||||
} else {
|
||||
GDTCORLogDebug(@"Writing archive succeeded: %@", filePath);
|
||||
completion(YES, nil);
|
||||
}
|
||||
|
||||
// Notify size tracker.
|
||||
[self.sizeTracker fileWasAddedAtPath:filePath withSize:encodedEvent.length];
|
||||
|
||||
// Check the QoS, if it's high priority, notify the target that it has a high priority event.
|
||||
if (event.qosTier == GDTCOREventQoSFast) {
|
||||
// TODO: Remove a direct dependency on the upload coordinator.
|
||||
[self.uploadCoordinator forceUploadForTarget:target];
|
||||
}
|
||||
|
||||
// Cancel or end the associated background task if it's still valid.
|
||||
[[GDTCORApplication sharedApplication] endBackgroundTask:bgID];
|
||||
bgID = GDTCORBackgroundIdentifierInvalid;
|
||||
});
|
||||
}
|
||||
|
||||
- (void)batchWithEventSelector:(nonnull GDTCORStorageEventSelector *)eventSelector
|
||||
batchExpiration:(nonnull NSDate *)expiration
|
||||
onComplete:
|
||||
(nonnull void (^)(NSNumber *_Nullable batchID,
|
||||
NSSet<GDTCOREvent *> *_Nullable events))onComplete {
|
||||
dispatch_queue_t queue = _storageQueue;
|
||||
void (^onPathsForTargetComplete)(NSNumber *, NSSet<NSString *> *_Nonnull) = ^(
|
||||
NSNumber *batchID, NSSet<NSString *> *_Nonnull paths) {
|
||||
dispatch_async(queue, ^{
|
||||
NSMutableSet<GDTCOREvent *> *events = [[NSMutableSet alloc] init];
|
||||
for (NSString *eventPath in paths) {
|
||||
NSError *error;
|
||||
GDTCOREvent *event =
|
||||
(GDTCOREvent *)GDTCORDecodeArchiveAtPath([GDTCOREvent class], eventPath, &error);
|
||||
if (event == nil || error) {
|
||||
GDTCORLogDebug(@"Error deserializing event: %@", error);
|
||||
[[NSFileManager defaultManager] removeItemAtPath:eventPath error:nil];
|
||||
continue;
|
||||
} else {
|
||||
NSString *fileName = [eventPath lastPathComponent];
|
||||
NSString *batchPath =
|
||||
[GDTCORFlatFileStorage batchPathForTarget:eventSelector.selectedTarget
|
||||
batchID:batchID
|
||||
expirationDate:expiration];
|
||||
[[NSFileManager defaultManager] createDirectoryAtPath:batchPath
|
||||
withIntermediateDirectories:YES
|
||||
attributes:nil
|
||||
error:nil];
|
||||
NSString *destinationPath = [batchPath stringByAppendingPathComponent:fileName];
|
||||
error = nil;
|
||||
[[NSFileManager defaultManager] moveItemAtPath:eventPath
|
||||
toPath:destinationPath
|
||||
error:&error];
|
||||
if (error) {
|
||||
GDTCORLogDebug(@"An event file wasn't moveable into the batch directory: %@", error);
|
||||
}
|
||||
[events addObject:event];
|
||||
}
|
||||
}
|
||||
if (onComplete) {
|
||||
if (events.count == 0) {
|
||||
onComplete(nil, nil);
|
||||
} else {
|
||||
onComplete(batchID, events);
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
void (^onBatchIDFetchComplete)(NSNumber *) = ^(NSNumber *batchID) {
|
||||
dispatch_async(queue, ^{
|
||||
if (batchID == nil) {
|
||||
if (onComplete) {
|
||||
onComplete(nil, nil);
|
||||
return;
|
||||
}
|
||||
}
|
||||
[self pathsForTarget:eventSelector.selectedTarget
|
||||
eventIDs:eventSelector.selectedEventIDs
|
||||
qosTiers:eventSelector.selectedQosTiers
|
||||
mappingIDs:eventSelector.selectedMappingIDs
|
||||
onComplete:^(NSSet<NSString *> *_Nonnull paths) {
|
||||
onPathsForTargetComplete(batchID, paths);
|
||||
}];
|
||||
});
|
||||
};
|
||||
|
||||
[self nextBatchID:^(NSNumber *_Nullable batchID) {
|
||||
if (batchID == nil) {
|
||||
if (onComplete) {
|
||||
onComplete(nil, nil);
|
||||
}
|
||||
} else {
|
||||
onBatchIDFetchComplete(batchID);
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)removeBatchWithID:(nonnull NSNumber *)batchID
|
||||
deleteEvents:(BOOL)deleteEvents
|
||||
onComplete:(void (^_Nullable)(void))onComplete {
|
||||
dispatch_async(_storageQueue, ^{
|
||||
[self syncThreadUnsafeRemoveBatchWithID:batchID deleteEvents:deleteEvents];
|
||||
|
||||
if (onComplete) {
|
||||
onComplete();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
- (void)batchIDsForTarget:(GDTCORTarget)target
|
||||
onComplete:(nonnull void (^)(NSSet<NSNumber *> *_Nullable))onComplete {
|
||||
dispatch_async(_storageQueue, ^{
|
||||
NSFileManager *fileManager = [NSFileManager defaultManager];
|
||||
NSError *error;
|
||||
NSArray<NSString *> *batchPaths =
|
||||
[fileManager contentsOfDirectoryAtPath:[GDTCORFlatFileStorage batchDataStoragePath]
|
||||
error:&error];
|
||||
if (error || batchPaths.count == 0) {
|
||||
if (onComplete) {
|
||||
onComplete(nil);
|
||||
}
|
||||
return;
|
||||
}
|
||||
NSMutableSet<NSNumber *> *batchIDs = [[NSMutableSet alloc] init];
|
||||
for (NSString *path in batchPaths) {
|
||||
NSDictionary<NSString *, id> *components = [self batchComponentsFromFilename:path];
|
||||
NSNumber *targetNumber = components[kGDTCORBatchComponentsTargetKey];
|
||||
NSNumber *batchID = components[kGDTCORBatchComponentsBatchIDKey];
|
||||
if (batchID != nil && targetNumber.intValue == target) {
|
||||
[batchIDs addObject:batchID];
|
||||
}
|
||||
}
|
||||
if (onComplete) {
|
||||
onComplete(batchIDs);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
- (void)libraryDataForKey:(nonnull NSString *)key
|
||||
onFetchComplete:(nonnull void (^)(NSData *_Nullable, NSError *_Nullable))onFetchComplete
|
||||
setNewValue:(NSData *_Nullable (^_Nullable)(void))setValueBlock {
|
||||
dispatch_async(_storageQueue, ^{
|
||||
NSString *dataPath = [[[self class] libraryDataStoragePath] stringByAppendingPathComponent:key];
|
||||
NSError *error;
|
||||
NSData *data = [NSData dataWithContentsOfFile:dataPath options:0 error:&error];
|
||||
if (onFetchComplete) {
|
||||
onFetchComplete(data, error);
|
||||
}
|
||||
if (setValueBlock) {
|
||||
NSData *newValue = setValueBlock();
|
||||
// The -isKindOfClass check is necessary because without an explicit 'return nil' in the block
|
||||
// the implicit return value will be the block itself. The compiler doesn't detect this.
|
||||
if (newValue != nil && [newValue isKindOfClass:[NSData class]] && newValue.length) {
|
||||
NSError *newValueError;
|
||||
if ([newValue writeToFile:dataPath options:NSDataWritingAtomic error:&newValueError]) {
|
||||
// Update storage size.
|
||||
[self.sizeTracker fileWasRemovedAtPath:dataPath withSize:data.length];
|
||||
[self.sizeTracker fileWasAddedAtPath:dataPath withSize:newValue.length];
|
||||
} else {
|
||||
GDTCORLogDebug(@"Error writing new value in libraryDataForKey: %@", newValueError);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
- (void)storeLibraryData:(NSData *)data
|
||||
forKey:(nonnull NSString *)key
|
||||
onComplete:(nullable void (^)(NSError *_Nullable error))onComplete {
|
||||
if (!data || data.length <= 0) {
|
||||
if (onComplete) {
|
||||
onComplete([NSError errorWithDomain:NSInternalInconsistencyException code:-1 userInfo:nil]);
|
||||
}
|
||||
return;
|
||||
}
|
||||
dispatch_async(_storageQueue, ^{
|
||||
NSError *error;
|
||||
NSString *dataPath = [[[self class] libraryDataStoragePath] stringByAppendingPathComponent:key];
|
||||
if ([data writeToFile:dataPath options:NSDataWritingAtomic error:&error]) {
|
||||
[self.sizeTracker fileWasAddedAtPath:dataPath withSize:data.length];
|
||||
}
|
||||
if (onComplete) {
|
||||
onComplete(error);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
- (void)removeLibraryDataForKey:(nonnull NSString *)key
|
||||
onComplete:(nonnull void (^)(NSError *_Nullable error))onComplete {
|
||||
dispatch_async(_storageQueue, ^{
|
||||
NSError *error;
|
||||
NSString *dataPath = [[[self class] libraryDataStoragePath] stringByAppendingPathComponent:key];
|
||||
GDTCORStorageSizeBytes fileSize =
|
||||
[self.sizeTracker fileSizeAtURL:[NSURL fileURLWithPath:dataPath]];
|
||||
|
||||
if ([[NSFileManager defaultManager] fileExistsAtPath:dataPath]) {
|
||||
if ([[NSFileManager defaultManager] removeItemAtPath:dataPath error:&error]) {
|
||||
[self.sizeTracker fileWasRemovedAtPath:dataPath withSize:fileSize];
|
||||
}
|
||||
if (onComplete) {
|
||||
onComplete(error);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
- (void)hasEventsForTarget:(GDTCORTarget)target onComplete:(void (^)(BOOL hasEvents))onComplete {
|
||||
dispatch_async(_storageQueue, ^{
|
||||
NSFileManager *fileManager = [NSFileManager defaultManager];
|
||||
NSString *targetPath = [NSString
|
||||
stringWithFormat:@"%@/%ld", [GDTCORFlatFileStorage eventDataStoragePath], (long)target];
|
||||
[fileManager createDirectoryAtPath:targetPath
|
||||
withIntermediateDirectories:YES
|
||||
attributes:nil
|
||||
error:nil];
|
||||
NSDirectoryEnumerator *enumerator = [fileManager enumeratorAtPath:targetPath];
|
||||
BOOL hasEventAtLeastOneEvent = [enumerator nextObject] != nil;
|
||||
if (onComplete) {
|
||||
onComplete(hasEventAtLeastOneEvent);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
- (void)checkForExpirations {
|
||||
dispatch_async(_storageQueue, ^{
|
||||
GDTCORLogDebug(@"%@", @"Checking for expired events and batches");
|
||||
NSTimeInterval now = [NSDate date].timeIntervalSince1970;
|
||||
NSFileManager *fileManager = [NSFileManager defaultManager];
|
||||
|
||||
// TODO: Storage may not have enough context to remove batches because a batch may be being
|
||||
// uploaded but the storage has not context of it.
|
||||
|
||||
// Find expired batches and move their events back to the main storage.
|
||||
// If a batch contains expired events they are expected to be removed further in the method
|
||||
// together with other expired events in the main storage.
|
||||
NSString *batchDataPath = [GDTCORFlatFileStorage batchDataStoragePath];
|
||||
NSArray<NSString *> *batchDataPaths = [fileManager contentsOfDirectoryAtPath:batchDataPath
|
||||
error:nil];
|
||||
for (NSString *path in batchDataPaths) {
|
||||
@autoreleasepool {
|
||||
NSString *fileName = [path lastPathComponent];
|
||||
NSDictionary<NSString *, id> *batchComponents = [self batchComponentsFromFilename:fileName];
|
||||
NSDate *expirationDate = batchComponents[kGDTCORBatchComponentsExpirationKey];
|
||||
NSNumber *batchID = batchComponents[kGDTCORBatchComponentsBatchIDKey];
|
||||
if (expirationDate != nil && expirationDate.timeIntervalSince1970 < now && batchID != nil) {
|
||||
NSNumber *batchID = batchComponents[kGDTCORBatchComponentsBatchIDKey];
|
||||
// Move all events from the expired batch back to the main storage.
|
||||
[self syncThreadUnsafeRemoveBatchWithID:batchID deleteEvents:NO];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Find expired events and remove them from the storage.
|
||||
NSMutableSet<GDTCOREvent *> *expiredEvents = [NSMutableSet set];
|
||||
NSString *eventDataPath = [GDTCORFlatFileStorage eventDataStoragePath];
|
||||
NSDirectoryEnumerator *enumerator = [fileManager enumeratorAtPath:eventDataPath];
|
||||
NSString *path;
|
||||
|
||||
while (YES) {
|
||||
@autoreleasepool {
|
||||
// Call `[enumerator nextObject]` under autorelease pool to make sure all autoreleased
|
||||
// objects created under the hood are released on each iteration end to avoid unnecessary
|
||||
// memory growth.
|
||||
path = [enumerator nextObject];
|
||||
if (path == nil) {
|
||||
break;
|
||||
}
|
||||
|
||||
NSString *fileName = [path lastPathComponent];
|
||||
NSDictionary<NSString *, id> *eventComponents = [self eventComponentsFromFilename:fileName];
|
||||
NSDate *expirationDate = eventComponents[kGDTCOREventComponentsExpirationKey];
|
||||
if (expirationDate != nil && expirationDate.timeIntervalSince1970 < now) {
|
||||
NSString *pathToDelete = [eventDataPath stringByAppendingPathComponent:path];
|
||||
|
||||
// Decode the expired event from the path to be deleted.
|
||||
NSError *decodeError;
|
||||
GDTCOREvent *event = (GDTCOREvent *)GDTCORDecodeArchiveAtPath([GDTCOREvent class],
|
||||
pathToDelete, &decodeError);
|
||||
if (event == nil || decodeError) {
|
||||
GDTCORLogDebug(@"Error deserializing event while checking for expired events: %@",
|
||||
decodeError);
|
||||
event = nil;
|
||||
}
|
||||
|
||||
// Remove the path to be deleted, adding the decoded event to the
|
||||
// event set if the removal was successful.
|
||||
NSError *removeError;
|
||||
[fileManager removeItemAtPath:pathToDelete error:&removeError];
|
||||
if (removeError != nil) {
|
||||
GDTCORLogDebug(@"There was an error deleting an expired item: %@", removeError);
|
||||
} else {
|
||||
GDTCORLogDebug(@"Item deleted because it expired: %@", pathToDelete);
|
||||
if (event) {
|
||||
[expiredEvents addObject:event];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (self.delegate != nil && [expiredEvents count] > 0) {
|
||||
GDTCORLogDebug(@"Delegate notified that %@ events were dropped.", @(expiredEvents.count));
|
||||
[self.delegate storage:self didRemoveExpiredEvents:[expiredEvents copy]];
|
||||
}
|
||||
|
||||
[self.sizeTracker resetCachedSize];
|
||||
});
|
||||
}
|
||||
|
||||
- (void)storageSizeWithCallback:(void (^)(uint64_t storageSize))onComplete {
|
||||
if (!onComplete) {
|
||||
return;
|
||||
}
|
||||
|
||||
dispatch_async(_storageQueue, ^{
|
||||
onComplete([self.sizeTracker directoryContentSize]);
|
||||
});
|
||||
}
|
||||
|
||||
#pragma mark - Private not thread safe methods
|
||||
/** Looks for directory paths containing events for a batch with the specified ID.
|
||||
* @param batchID A batch ID.
|
||||
* @param outError A pointer to `NSError *` to assign as possible error to.
|
||||
* @return An array of an array of paths to directories for event batches with a specified batch ID
|
||||
* or `nil` in the case of an error. Usually returns a single path but potentially return more in
|
||||
* cases when the app is terminated while uploading a batch.
|
||||
*/
|
||||
- (nullable NSArray<NSString *> *)batchDirPathsForBatchID:(NSNumber *)batchID
|
||||
error:(NSError **_Nonnull)outError {
|
||||
NSFileManager *fileManager = [NSFileManager defaultManager];
|
||||
NSError *error;
|
||||
NSArray<NSString *> *batches =
|
||||
[fileManager contentsOfDirectoryAtPath:[GDTCORFlatFileStorage batchDataStoragePath]
|
||||
error:&error];
|
||||
if (batches == nil) {
|
||||
*outError = error;
|
||||
GDTCORLogDebug(@"Failed to find event file paths for batchID: %@, error: %@", batchID, error);
|
||||
return nil;
|
||||
}
|
||||
|
||||
NSMutableArray<NSString *> *batchDirPaths = [NSMutableArray array];
|
||||
for (NSString *path in batches) {
|
||||
NSDictionary<NSString *, id> *components = [self batchComponentsFromFilename:path];
|
||||
NSNumber *pathBatchID = components[kGDTCORBatchComponentsBatchIDKey];
|
||||
if ([pathBatchID isEqual:batchID]) {
|
||||
NSString *batchDirPath =
|
||||
[[GDTCORFlatFileStorage batchDataStoragePath] stringByAppendingPathComponent:path];
|
||||
[batchDirPaths addObject:batchDirPath];
|
||||
}
|
||||
}
|
||||
|
||||
return [batchDirPaths copy];
|
||||
}
|
||||
|
||||
/** Makes a copy of the contents of a directory to a directory at the specified path.*/
|
||||
- (BOOL)moveContentsOfDirectoryAtPath:(NSString *)sourcePath
|
||||
to:(NSString *)destinationPath
|
||||
error:(NSError **_Nonnull)outError {
|
||||
NSFileManager *fileManager = [NSFileManager defaultManager];
|
||||
|
||||
NSError *error;
|
||||
NSArray<NSString *> *contentsPaths = [fileManager contentsOfDirectoryAtPath:sourcePath
|
||||
error:&error];
|
||||
if (contentsPaths == nil) {
|
||||
*outError = error;
|
||||
return NO;
|
||||
}
|
||||
|
||||
NSMutableArray<NSError *> *errors = [NSMutableArray array];
|
||||
for (NSString *path in contentsPaths) {
|
||||
NSString *contentDestinationPath = [destinationPath stringByAppendingPathComponent:path];
|
||||
NSString *contentSourcePath = [sourcePath stringByAppendingPathComponent:path];
|
||||
|
||||
NSError *moveError;
|
||||
if (![fileManager moveItemAtPath:contentSourcePath
|
||||
toPath:contentDestinationPath
|
||||
error:&moveError] &&
|
||||
moveError) {
|
||||
[errors addObject:moveError];
|
||||
}
|
||||
}
|
||||
|
||||
if (errors.count == 0) {
|
||||
return YES;
|
||||
} else {
|
||||
NSError *combinedError = [NSError errorWithDomain:@"GDTCORFlatFileStorage"
|
||||
code:-1
|
||||
userInfo:@{NSUnderlyingErrorKey : errors}];
|
||||
*outError = combinedError;
|
||||
return NO;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)syncThreadUnsafeRemoveBatchWithID:(nonnull NSNumber *)batchID
|
||||
deleteEvents:(BOOL)deleteEvents {
|
||||
NSError *error;
|
||||
NSArray<NSString *> *batchDirPaths = [self batchDirPathsForBatchID:batchID error:&error];
|
||||
|
||||
if (batchDirPaths == nil) {
|
||||
return;
|
||||
}
|
||||
|
||||
NSFileManager *fileManager = [NSFileManager defaultManager];
|
||||
|
||||
void (^removeBatchDir)(NSString *batchDirPath) = ^(NSString *batchDirPath) {
|
||||
NSError *error;
|
||||
if ([fileManager removeItemAtPath:batchDirPath error:&error]) {
|
||||
GDTCORLogDebug(@"Batch removed at path: %@", batchDirPath);
|
||||
} else {
|
||||
GDTCORLogDebug(@"Failed to remove batch at path: %@", batchDirPath);
|
||||
}
|
||||
};
|
||||
|
||||
for (NSString *batchDirPath in batchDirPaths) {
|
||||
@autoreleasepool {
|
||||
if (deleteEvents) {
|
||||
removeBatchDir(batchDirPath);
|
||||
} else {
|
||||
NSString *batchDirName = [batchDirPath lastPathComponent];
|
||||
NSDictionary<NSString *, id> *components = [self batchComponentsFromFilename:batchDirName];
|
||||
NSString *targetValue = [components[kGDTCORBatchComponentsTargetKey] stringValue];
|
||||
NSString *destinationPath;
|
||||
if (targetValue) {
|
||||
destinationPath = [[GDTCORFlatFileStorage eventDataStoragePath]
|
||||
stringByAppendingPathComponent:targetValue];
|
||||
}
|
||||
|
||||
// `- [NSFileManager moveItemAtPath:toPath:error:]` method fails if an item by the
|
||||
// destination path already exists (which usually is the case for the current method). Move
|
||||
// the events one by one instead.
|
||||
if (destinationPath && [self moveContentsOfDirectoryAtPath:batchDirPath
|
||||
to:destinationPath
|
||||
error:&error]) {
|
||||
GDTCORLogDebug(@"Batched events at path: %@ moved back to the storage: %@", batchDirPath,
|
||||
destinationPath);
|
||||
} else {
|
||||
GDTCORLogDebug(@"Error encountered whilst moving events back: %@", error);
|
||||
}
|
||||
|
||||
// Even if not all events where moved back to the storage, there is not much can be done at
|
||||
// this point, so cleanup batch directory now to avoid cluttering.
|
||||
removeBatchDir(batchDirPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[self.sizeTracker resetCachedSize];
|
||||
}
|
||||
|
||||
#pragma mark - Private helper methods
|
||||
|
||||
+ (NSString *)eventDataStoragePath {
|
||||
static NSString *eventDataPath;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
eventDataPath = [NSString stringWithFormat:@"%@/%@/gdt_event_data", GDTCORRootDirectory().path,
|
||||
NSStringFromClass([self class])];
|
||||
});
|
||||
NSError *error;
|
||||
[[NSFileManager defaultManager] createDirectoryAtPath:eventDataPath
|
||||
withIntermediateDirectories:YES
|
||||
attributes:0
|
||||
error:&error];
|
||||
GDTCORAssert(error == nil, @"Creating the library data path failed: %@", error);
|
||||
return eventDataPath;
|
||||
}
|
||||
|
||||
+ (NSString *)batchDataStoragePath {
|
||||
static NSString *batchDataPath;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
batchDataPath = [NSString stringWithFormat:@"%@/%@/gdt_batch_data", GDTCORRootDirectory().path,
|
||||
NSStringFromClass([self class])];
|
||||
});
|
||||
NSError *error;
|
||||
[[NSFileManager defaultManager] createDirectoryAtPath:batchDataPath
|
||||
withIntermediateDirectories:YES
|
||||
attributes:0
|
||||
error:&error];
|
||||
GDTCORAssert(error == nil, @"Creating the batch data path failed: %@", error);
|
||||
return batchDataPath;
|
||||
}
|
||||
|
||||
+ (NSString *)libraryDataStoragePath {
|
||||
static NSString *libraryDataPath;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
libraryDataPath =
|
||||
[NSString stringWithFormat:@"%@/%@/gdt_library_data", GDTCORRootDirectory().path,
|
||||
NSStringFromClass([self class])];
|
||||
});
|
||||
NSError *error;
|
||||
[[NSFileManager defaultManager] createDirectoryAtPath:libraryDataPath
|
||||
withIntermediateDirectories:YES
|
||||
attributes:0
|
||||
error:&error];
|
||||
GDTCORAssert(error == nil, @"Creating the library data path failed: %@", error);
|
||||
return libraryDataPath;
|
||||
}
|
||||
|
||||
+ (NSString *)batchPathForTarget:(GDTCORTarget)target
|
||||
batchID:(NSNumber *)batchID
|
||||
expirationDate:(NSDate *)expirationDate {
|
||||
return
|
||||
[NSString stringWithFormat:@"%@/%ld%@%@%@%llu", [GDTCORFlatFileStorage batchDataStoragePath],
|
||||
(long)target, kMetadataSeparator, batchID, kMetadataSeparator,
|
||||
((uint64_t)expirationDate.timeIntervalSince1970)];
|
||||
}
|
||||
|
||||
+ (NSString *)pathForTarget:(GDTCORTarget)target
|
||||
eventID:(NSString *)eventID
|
||||
qosTier:(NSNumber *)qosTier
|
||||
expirationDate:(NSDate *)expirationDate
|
||||
mappingID:(NSString *)mappingID {
|
||||
NSMutableCharacterSet *allowedChars = [[NSCharacterSet alphanumericCharacterSet] mutableCopy];
|
||||
[allowedChars addCharactersInString:kMetadataSeparator];
|
||||
mappingID = [mappingID stringByAddingPercentEncodingWithAllowedCharacters:allowedChars];
|
||||
return [NSString stringWithFormat:@"%@/%ld/%@%@%@%@%llu%@%@",
|
||||
[GDTCORFlatFileStorage eventDataStoragePath], (long)target,
|
||||
eventID, kMetadataSeparator, qosTier, kMetadataSeparator,
|
||||
((uint64_t)expirationDate.timeIntervalSince1970),
|
||||
kMetadataSeparator, mappingID];
|
||||
}
|
||||
|
||||
- (void)pathsForTarget:(GDTCORTarget)target
|
||||
eventIDs:(nullable NSSet<NSString *> *)eventIDs
|
||||
qosTiers:(nullable NSSet<NSNumber *> *)qosTiers
|
||||
mappingIDs:(nullable NSSet<NSString *> *)mappingIDs
|
||||
onComplete:(void (^)(NSSet<NSString *> *paths))onComplete {
|
||||
void (^completion)(NSSet<NSString *> *) = onComplete == nil ? ^(NSSet<NSString *> *paths){} : onComplete;
|
||||
dispatch_async(_storageQueue, ^{
|
||||
NSMutableSet<NSString *> *paths = [[NSMutableSet alloc] init];
|
||||
NSFileManager *fileManager = [NSFileManager defaultManager];
|
||||
NSString *targetPath = [NSString
|
||||
stringWithFormat:@"%@/%ld", [GDTCORFlatFileStorage eventDataStoragePath], (long)target];
|
||||
[fileManager createDirectoryAtPath:targetPath
|
||||
withIntermediateDirectories:YES
|
||||
attributes:nil
|
||||
error:nil];
|
||||
NSError *error;
|
||||
NSArray<NSString *> *dirPaths = [fileManager contentsOfDirectoryAtPath:targetPath error:&error];
|
||||
if (error) {
|
||||
GDTCORLogDebug(@"There was an error reading the contents of the target path: %@", error);
|
||||
completion(paths);
|
||||
return;
|
||||
}
|
||||
BOOL checkingIDs = eventIDs.count > 0;
|
||||
BOOL checkingQosTiers = qosTiers.count > 0;
|
||||
BOOL checkingMappingIDs = mappingIDs.count > 0;
|
||||
BOOL checkingAnything = checkingIDs == NO && checkingQosTiers == NO && checkingMappingIDs == NO;
|
||||
for (NSString *path in dirPaths) {
|
||||
// Skip hidden files that are created as part of atomic file creation.
|
||||
if ([path hasPrefix:@"."]) {
|
||||
continue;
|
||||
}
|
||||
NSString *filePath = [targetPath stringByAppendingPathComponent:path];
|
||||
if (checkingAnything) {
|
||||
[paths addObject:filePath];
|
||||
continue;
|
||||
}
|
||||
NSString *filename = [path lastPathComponent];
|
||||
NSDictionary<NSString *, id> *eventComponents = [self eventComponentsFromFilename:filename];
|
||||
if (!eventComponents) {
|
||||
GDTCORLogDebug(@"There was an error reading the filename components: %@", eventComponents);
|
||||
continue;
|
||||
}
|
||||
NSString *eventID = eventComponents[kGDTCOREventComponentsEventIDKey];
|
||||
NSNumber *qosTier = eventComponents[kGDTCOREventComponentsQoSTierKey];
|
||||
NSString *mappingID = eventComponents[kGDTCOREventComponentsMappingIDKey];
|
||||
|
||||
NSNumber *eventIDMatch = checkingIDs ? @([eventIDs containsObject:eventID]) : nil;
|
||||
NSNumber *qosTierMatch = checkingQosTiers ? @([qosTiers containsObject:qosTier]) : nil;
|
||||
NSNumber *mappingIDMatch =
|
||||
checkingMappingIDs
|
||||
? @([mappingIDs containsObject:[mappingID stringByRemovingPercentEncoding]])
|
||||
: nil;
|
||||
if ((eventIDMatch == nil || eventIDMatch.boolValue) &&
|
||||
(qosTierMatch == nil || qosTierMatch.boolValue) &&
|
||||
(mappingIDMatch == nil || mappingIDMatch.boolValue)) {
|
||||
[paths addObject:filePath];
|
||||
}
|
||||
}
|
||||
completion(paths);
|
||||
});
|
||||
}
|
||||
|
||||
- (void)nextBatchID:(void (^)(NSNumber *_Nullable batchID))nextBatchID {
|
||||
__block int32_t lastBatchID = -1;
|
||||
[self libraryDataForKey:gBatchIDCounterKey
|
||||
onFetchComplete:^(NSData *_Nullable data, NSError *_Nullable getValueError) {
|
||||
if (!getValueError) {
|
||||
[data getBytes:(void *)&lastBatchID length:sizeof(int32_t)];
|
||||
}
|
||||
if (data == nil) {
|
||||
lastBatchID = 0;
|
||||
}
|
||||
if (nextBatchID) {
|
||||
nextBatchID(@(lastBatchID));
|
||||
}
|
||||
}
|
||||
setNewValue:^NSData *_Nullable(void) {
|
||||
if (lastBatchID != -1) {
|
||||
int32_t incrementedValue = lastBatchID + 1;
|
||||
return [NSData dataWithBytes:&incrementedValue length:sizeof(int32_t)];
|
||||
}
|
||||
return nil;
|
||||
}];
|
||||
}
|
||||
|
||||
- (nullable NSDictionary<NSString *, id> *)eventComponentsFromFilename:(NSString *)fileName {
|
||||
NSArray<NSString *> *components = [fileName componentsSeparatedByString:kMetadataSeparator];
|
||||
if (components.count >= 4) {
|
||||
NSString *eventID = components[0];
|
||||
NSNumber *qosTier = @(components[1].integerValue);
|
||||
NSDate *expirationDate = [NSDate dateWithTimeIntervalSince1970:components[2].longLongValue];
|
||||
NSString *mappingID = [[components subarrayWithRange:NSMakeRange(3, components.count - 3)]
|
||||
componentsJoinedByString:kMetadataSeparator];
|
||||
if (eventID == nil || qosTier == nil || mappingID == nil || expirationDate == nil) {
|
||||
GDTCORLogDebug(@"There was an error parsing the event filename components: %@", components);
|
||||
return nil;
|
||||
}
|
||||
return @{
|
||||
kGDTCOREventComponentsEventIDKey : eventID,
|
||||
kGDTCOREventComponentsQoSTierKey : qosTier,
|
||||
kGDTCOREventComponentsExpirationKey : expirationDate,
|
||||
kGDTCOREventComponentsMappingIDKey : mappingID
|
||||
};
|
||||
}
|
||||
GDTCORLogDebug(@"The event filename could not be split: %@", fileName);
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (nullable NSDictionary<NSString *, id> *)batchComponentsFromFilename:(NSString *)fileName {
|
||||
NSArray<NSString *> *components = [fileName componentsSeparatedByString:kMetadataSeparator];
|
||||
if (components.count == 3) {
|
||||
NSNumber *target = @(components[0].integerValue);
|
||||
NSNumber *batchID = @(components[1].integerValue);
|
||||
NSDate *expirationDate = [NSDate dateWithTimeIntervalSince1970:components[2].doubleValue];
|
||||
if (target == nil || batchID == nil || expirationDate == nil) {
|
||||
GDTCORLogDebug(@"There was an error parsing the batch filename components: %@", components);
|
||||
return nil;
|
||||
}
|
||||
return @{
|
||||
kGDTCORBatchComponentsTargetKey : target,
|
||||
kGDTCORBatchComponentsBatchIDKey : batchID,
|
||||
kGDTCORBatchComponentsExpirationKey : expirationDate
|
||||
};
|
||||
}
|
||||
GDTCORLogDebug(@"The batch filename could not be split: %@", fileName);
|
||||
return nil;
|
||||
}
|
||||
|
||||
#pragma mark - GDTCORLifecycleProtocol
|
||||
|
||||
- (void)appWillBackground:(GDTCORApplication *)app {
|
||||
dispatch_async(_storageQueue, ^{
|
||||
// Immediately request a background task to run until the end of the current queue of work,
|
||||
// and cancel it once the work is done.
|
||||
__block GDTCORBackgroundIdentifier bgID =
|
||||
[app beginBackgroundTaskWithName:@"GDTStorage"
|
||||
expirationHandler:^{
|
||||
[app endBackgroundTask:bgID];
|
||||
bgID = GDTCORBackgroundIdentifierInvalid;
|
||||
}];
|
||||
// End the background task if it's still valid.
|
||||
[app endBackgroundTask:bgID];
|
||||
bgID = GDTCORBackgroundIdentifierInvalid;
|
||||
});
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
118
Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORLifecycle.m
generated
Normal file
118
Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORLifecycle.m
generated
Normal file
@ -0,0 +1,118 @@
|
||||
/*
|
||||
* Copyright 2019 Google
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Internal/GDTCORLifecycle.h"
|
||||
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORConsoleLogger.h"
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCOREvent.h"
|
||||
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Private/GDTCORRegistrar_Private.h"
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Private/GDTCORTransformer_Private.h"
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Private/GDTCORUploadCoordinator.h"
|
||||
|
||||
@implementation GDTCORLifecycle
|
||||
|
||||
+ (void)load {
|
||||
[self sharedInstance];
|
||||
}
|
||||
|
||||
/** Creates/returns the singleton instance of this class.
|
||||
*
|
||||
* @return The singleton instance of this class.
|
||||
*/
|
||||
+ (instancetype)sharedInstance {
|
||||
static GDTCORLifecycle *sharedInstance;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
sharedInstance = [[GDTCORLifecycle alloc] init];
|
||||
});
|
||||
return sharedInstance;
|
||||
}
|
||||
|
||||
- (instancetype)init {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
|
||||
[notificationCenter addObserver:self
|
||||
selector:@selector(applicationDidEnterBackgroundNotification:)
|
||||
name:kGDTCORApplicationDidEnterBackgroundNotification
|
||||
object:nil];
|
||||
[notificationCenter addObserver:self
|
||||
selector:@selector(applicationWillEnterForegroundNotification:)
|
||||
name:kGDTCORApplicationWillEnterForegroundNotification
|
||||
object:nil];
|
||||
|
||||
[notificationCenter addObserver:self
|
||||
selector:@selector(applicationWillTerminateNotification:)
|
||||
name:kGDTCORApplicationWillTerminateNotification
|
||||
object:nil];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
||||
}
|
||||
|
||||
- (void)applicationDidEnterBackgroundNotification:(NSNotification *)notification {
|
||||
GDTCORApplication *application = [GDTCORApplication sharedApplication];
|
||||
if ([[GDTCORTransformer sharedInstance] respondsToSelector:@selector(appWillBackground:)]) {
|
||||
GDTCORLogDebug(@"%@", @"Signaling GDTCORTransformer that the app is backgrounding.");
|
||||
[[GDTCORTransformer sharedInstance] appWillBackground:application];
|
||||
}
|
||||
if ([[GDTCORUploadCoordinator sharedInstance] respondsToSelector:@selector(appWillBackground:)]) {
|
||||
GDTCORLogDebug(@"%@", @"Signaling GDTCORUploadCoordinator that the app is backgrounding.");
|
||||
[[GDTCORUploadCoordinator sharedInstance] appWillBackground:application];
|
||||
}
|
||||
if ([[GDTCORRegistrar sharedInstance] respondsToSelector:@selector(appWillBackground:)]) {
|
||||
GDTCORLogDebug(@"%@", @"Signaling GDTCORRegistrar that the app is backgrounding.");
|
||||
[[GDTCORRegistrar sharedInstance] appWillBackground:application];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)applicationWillEnterForegroundNotification:(NSNotification *)notification {
|
||||
GDTCORApplication *application = [GDTCORApplication sharedApplication];
|
||||
if ([[GDTCORTransformer sharedInstance] respondsToSelector:@selector(appWillForeground:)]) {
|
||||
GDTCORLogDebug(@"%@", @"Signaling GDTCORTransformer that the app is foregrounding.");
|
||||
[[GDTCORTransformer sharedInstance] appWillForeground:application];
|
||||
}
|
||||
if ([[GDTCORUploadCoordinator sharedInstance] respondsToSelector:@selector(appWillForeground:)]) {
|
||||
GDTCORLogDebug(@"%@", @"Signaling GDTCORUploadCoordinator that the app is foregrounding.");
|
||||
[[GDTCORUploadCoordinator sharedInstance] appWillForeground:application];
|
||||
}
|
||||
if ([[GDTCORRegistrar sharedInstance] respondsToSelector:@selector(appWillForeground:)]) {
|
||||
GDTCORLogDebug(@"%@", @"Signaling GDTCORRegistrar that the app is foregrounding.");
|
||||
[[GDTCORRegistrar sharedInstance] appWillForeground:application];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)applicationWillTerminateNotification:(NSNotification *)notification {
|
||||
GDTCORApplication *application = [GDTCORApplication sharedApplication];
|
||||
if ([[GDTCORTransformer sharedInstance] respondsToSelector:@selector(appWillTerminate:)]) {
|
||||
GDTCORLogDebug(@"%@", @"Signaling GDTCORTransformer that the app is terminating.");
|
||||
[[GDTCORTransformer sharedInstance] appWillTerminate:application];
|
||||
}
|
||||
if ([[GDTCORUploadCoordinator sharedInstance] respondsToSelector:@selector(appWillTerminate:)]) {
|
||||
GDTCORLogDebug(@"%@", @"Signaling GDTCORUploadCoordinator that the app is terminating.");
|
||||
[[GDTCORUploadCoordinator sharedInstance] appWillTerminate:application];
|
||||
}
|
||||
if ([[GDTCORRegistrar sharedInstance] respondsToSelector:@selector(appWillTerminate:)]) {
|
||||
GDTCORLogDebug(@"%@", @"Signaling GDTCORRegistrar that the app is terminating.");
|
||||
[[GDTCORRegistrar sharedInstance] appWillTerminate:application];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
184
Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORLogSourceMetrics.m
generated
Normal file
184
Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORLogSourceMetrics.m
generated
Normal file
@ -0,0 +1,184 @@
|
||||
// Copyright 2022 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Private/GDTCORLogSourceMetrics.h"
|
||||
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCOREvent.h"
|
||||
|
||||
static NSString *const kDroppedEventCounterByLogSource = @"droppedEventCounterByLogSource";
|
||||
|
||||
typedef NSDictionary<NSNumber *, NSNumber *> GDTCORDroppedEventCounter;
|
||||
|
||||
@interface GDTCORLogSourceMetrics ()
|
||||
|
||||
/// A dictionary of log sources that map to counters that reflect the number of events dropped for a
|
||||
/// given set of reasons (``GDTCOREventDropReason``).
|
||||
@property(nonatomic, readonly)
|
||||
NSDictionary<NSString *, GDTCORDroppedEventCounter *> *droppedEventCounterByLogSource;
|
||||
|
||||
@end
|
||||
|
||||
@implementation GDTCORLogSourceMetrics
|
||||
|
||||
+ (instancetype)metrics {
|
||||
return [[self alloc] initWithDroppedEventCounterByLogSource:@{}];
|
||||
}
|
||||
|
||||
+ (instancetype)metricsWithEvents:(NSArray<GDTCOREvent *> *)events
|
||||
droppedForReason:(GDTCOREventDropReason)reason {
|
||||
NSMutableDictionary<NSString *, GDTCORDroppedEventCounter *> *eventCounterByLogSource =
|
||||
[NSMutableDictionary dictionary];
|
||||
|
||||
for (GDTCOREvent *event in [events copy]) {
|
||||
// Dropped events with a `nil` or empty mapping ID (log source) are not recorded.
|
||||
if (event.mappingID.length == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Get the dropped event counter for the event's mapping ID (log source).
|
||||
// If the dropped event counter for this event's mapping ID is `nil`,
|
||||
// an empty mutable counter is returned.
|
||||
NSMutableDictionary<NSNumber *, NSNumber *> *eventCounter = [NSMutableDictionary
|
||||
dictionaryWithDictionary:eventCounterByLogSource[event.mappingID] ?: @{}];
|
||||
|
||||
// Increment the log source metrics for the given reason.
|
||||
NSInteger currentEventCountForReason = [eventCounter[@(reason)] integerValue];
|
||||
NSInteger updatedEventCountForReason = currentEventCountForReason + 1;
|
||||
|
||||
eventCounter[@(reason)] = @(updatedEventCountForReason);
|
||||
|
||||
// Update the mapping ID's (log source's) event counter with an immutable
|
||||
// copy of the updated counter.
|
||||
eventCounterByLogSource[event.mappingID] = [eventCounter copy];
|
||||
}
|
||||
|
||||
return [[self alloc] initWithDroppedEventCounterByLogSource:[eventCounterByLogSource copy]];
|
||||
}
|
||||
|
||||
- (instancetype)initWithDroppedEventCounterByLogSource:
|
||||
(NSDictionary<NSString *, GDTCORDroppedEventCounter *> *)droppedEventCounterByLogSource {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_droppedEventCounterByLogSource = [droppedEventCounterByLogSource copy];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (GDTCORLogSourceMetrics *)logSourceMetricsByMergingWithLogSourceMetrics:
|
||||
(GDTCORLogSourceMetrics *)metrics {
|
||||
// Create new log source metrics by merging the current metrics with the given metrics.
|
||||
NSDictionary<NSString *, GDTCORDroppedEventCounter *> *mergedEventCounterByLogSource = [[self
|
||||
class] dictionaryByMergingDictionary:self.droppedEventCounterByLogSource
|
||||
withOtherDictionary:metrics.droppedEventCounterByLogSource
|
||||
uniquingKeysWithBlock:^NSDictionary *(NSDictionary *eventCounter1,
|
||||
NSDictionary *eventCounter2) {
|
||||
return [[self class]
|
||||
dictionaryByMergingDictionary:eventCounter1
|
||||
withOtherDictionary:eventCounter2
|
||||
uniquingKeysWithBlock:^NSNumber *(NSNumber *eventCount1,
|
||||
NSNumber *eventCount2) {
|
||||
return @(eventCount1.integerValue + eventCount2.integerValue);
|
||||
}];
|
||||
}];
|
||||
|
||||
return
|
||||
[[[self class] alloc] initWithDroppedEventCounterByLogSource:mergedEventCounterByLogSource];
|
||||
}
|
||||
|
||||
/// Creates a new dictionary by merging together two given dictionaries.
|
||||
/// @param dictionary A dictionary for merging.
|
||||
/// @param otherDictionary Another dictionary for merging.
|
||||
/// @param block A block that is called with the values for any duplicate keys that are encountered.
|
||||
/// The block returns the desired value for the merged dictionary.
|
||||
+ (NSDictionary *)dictionaryByMergingDictionary:(NSDictionary *)dictionary
|
||||
withOtherDictionary:(NSDictionary *)otherDictionary
|
||||
uniquingKeysWithBlock:(id (^)(id value1, id value2))block {
|
||||
NSMutableDictionary *mergedDictionary = [NSMutableDictionary dictionaryWithDictionary:dictionary];
|
||||
|
||||
[otherDictionary enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
|
||||
if (mergedDictionary[key] != nil) {
|
||||
// The key exists in both given dictionaries so combine the corresponding values with the
|
||||
// given block.
|
||||
id newValue = block(mergedDictionary[key], obj);
|
||||
mergedDictionary[key] = newValue;
|
||||
} else {
|
||||
mergedDictionary[key] = obj;
|
||||
}
|
||||
}];
|
||||
|
||||
return [mergedDictionary copy];
|
||||
}
|
||||
|
||||
#pragma mark - Equality
|
||||
|
||||
- (BOOL)isEqualToLogSourceMetrics:(GDTCORLogSourceMetrics *)otherMetrics {
|
||||
return [_droppedEventCounterByLogSource
|
||||
isEqualToDictionary:otherMetrics.droppedEventCounterByLogSource];
|
||||
}
|
||||
|
||||
- (BOOL)isEqual:(nullable id)object {
|
||||
if (object == nil) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
if (self == object) {
|
||||
return YES;
|
||||
}
|
||||
|
||||
if (![object isKindOfClass:[self class]]) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
return [self isEqualToLogSourceMetrics:(GDTCORLogSourceMetrics *)object];
|
||||
}
|
||||
|
||||
- (NSUInteger)hash {
|
||||
return [_droppedEventCounterByLogSource hash];
|
||||
}
|
||||
|
||||
#pragma mark - NSSecureCoding
|
||||
|
||||
+ (BOOL)supportsSecureCoding {
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (nullable instancetype)initWithCoder:(nonnull NSCoder *)coder {
|
||||
NSDictionary<NSString *, GDTCORDroppedEventCounter *> *droppedEventCounterByLogSource =
|
||||
[coder decodeObjectOfClasses:
|
||||
[NSSet setWithArray:@[ NSDictionary.class, NSString.class, NSNumber.class ]]
|
||||
forKey:kDroppedEventCounterByLogSource];
|
||||
|
||||
if (!droppedEventCounterByLogSource ||
|
||||
![droppedEventCounterByLogSource isKindOfClass:[NSDictionary class]]) {
|
||||
// If any of the fields are corrupted, the initializer should fail.
|
||||
return nil;
|
||||
}
|
||||
|
||||
return [self initWithDroppedEventCounterByLogSource:droppedEventCounterByLogSource];
|
||||
}
|
||||
|
||||
- (void)encodeWithCoder:(nonnull NSCoder *)coder {
|
||||
[coder encodeObject:self.droppedEventCounterByLogSource forKey:kDroppedEventCounterByLogSource];
|
||||
}
|
||||
|
||||
#pragma mark - Description
|
||||
|
||||
- (NSString *)description {
|
||||
return [NSString
|
||||
stringWithFormat:@"%@ %@", [super description], self.droppedEventCounterByLogSource];
|
||||
}
|
||||
|
||||
@end
|
||||
100
Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORMetrics.m
generated
Normal file
100
Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORMetrics.m
generated
Normal file
@ -0,0 +1,100 @@
|
||||
// Copyright 2022 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Private/GDTCORMetrics.h"
|
||||
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Private/GDTCORLogSourceMetrics.h"
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Private/GDTCORMetricsMetadata.h"
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Private/GDTCORStorageMetadata.h"
|
||||
|
||||
@implementation GDTCORMetrics
|
||||
|
||||
- (instancetype)initWithCollectionStartDate:(NSDate *)collectionStartDate
|
||||
collectionEndDate:(NSDate *)collectionEndDate
|
||||
logSourceMetrics:(GDTCORLogSourceMetrics *)logSourceMetrics
|
||||
currentCacheSize:(GDTCORStorageSizeBytes)currentCacheSize
|
||||
maxCacheSize:(GDTCORStorageSizeBytes)maxCacheSize
|
||||
bundleID:(NSString *)bundleID {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_collectionStartDate = [collectionStartDate copy];
|
||||
_collectionEndDate = [collectionEndDate copy];
|
||||
_logSourceMetrics = logSourceMetrics;
|
||||
_currentCacheSize = currentCacheSize;
|
||||
_maxCacheSize = maxCacheSize;
|
||||
_bundleID = [bundleID copy];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
+ (instancetype)metricsWithMetricsMetadata:(GDTCORMetricsMetadata *)metricsMetadata
|
||||
storageMetadata:(GDTCORStorageMetadata *)storageMetadata {
|
||||
// The window of collection ends at the time of creating the metrics object.
|
||||
NSDate *collectionEndDate = [NSDate date];
|
||||
// The main bundle ID is associated with the created metrics.
|
||||
NSString *bundleID = [[NSBundle mainBundle] bundleIdentifier] ?: @"";
|
||||
|
||||
return [[GDTCORMetrics alloc] initWithCollectionStartDate:metricsMetadata.collectionStartDate
|
||||
collectionEndDate:collectionEndDate
|
||||
logSourceMetrics:metricsMetadata.logSourceMetrics
|
||||
currentCacheSize:storageMetadata.currentCacheSize
|
||||
maxCacheSize:storageMetadata.maxCacheSize
|
||||
bundleID:bundleID];
|
||||
}
|
||||
|
||||
#pragma mark - Equality
|
||||
|
||||
- (BOOL)isEqualToMetrics:(GDTCORMetrics *)otherMetrics {
|
||||
return [self.collectionStartDate isEqualToDate:otherMetrics.collectionStartDate] &&
|
||||
[self.collectionEndDate isEqualToDate:otherMetrics.collectionEndDate] &&
|
||||
[self.logSourceMetrics isEqualToLogSourceMetrics:otherMetrics.logSourceMetrics] &&
|
||||
[self.bundleID isEqualToString:otherMetrics.bundleID] &&
|
||||
self.currentCacheSize == otherMetrics.currentCacheSize &&
|
||||
self.maxCacheSize == otherMetrics.maxCacheSize;
|
||||
}
|
||||
|
||||
- (BOOL)isEqual:(nullable id)object {
|
||||
if (object == nil) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
if (self == object) {
|
||||
return YES;
|
||||
}
|
||||
|
||||
if (![object isKindOfClass:[self class]]) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
return [self isEqualToMetrics:(GDTCORMetrics *)object];
|
||||
}
|
||||
|
||||
- (NSUInteger)hash {
|
||||
return [self.collectionStartDate hash] ^ [self.collectionEndDate hash] ^
|
||||
[self.logSourceMetrics hash] ^ [self.bundleID hash] ^ [@(self.currentCacheSize) hash] ^
|
||||
[@(self.maxCacheSize) hash];
|
||||
}
|
||||
|
||||
#pragma mark - Description
|
||||
|
||||
- (NSString *)description {
|
||||
return [NSString
|
||||
stringWithFormat:
|
||||
@"%@ {\n\tcollectionStartDate: %@,\n\tcollectionEndDate: %@,\n\tcurrentCacheSize: "
|
||||
@"%llu,\n\tmaxCacheSize: %llu,\n\tbundleID: %@,\n\tlogSourceMetrics: %@}\n",
|
||||
[super description], self.collectionStartDate, self.collectionEndDate,
|
||||
self.currentCacheSize, self.maxCacheSize, self.bundleID, self.logSourceMetrics];
|
||||
}
|
||||
|
||||
@end
|
||||
201
Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORMetricsController.m
generated
Normal file
201
Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORMetricsController.m
generated
Normal file
@ -0,0 +1,201 @@
|
||||
// Copyright 2022 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Private/GDTCORMetricsController.h"
|
||||
|
||||
#if __has_include(<FBLPromises/FBLPromises.h>)
|
||||
#import <FBLPromises/FBLPromises.h>
|
||||
#else
|
||||
#import "FBLPromises.h"
|
||||
#endif
|
||||
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORConsoleLogger.h"
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCOREvent.h"
|
||||
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Internal/GDTCORRegistrar.h"
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Internal/GDTCORStorageProtocol.h"
|
||||
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Private/GDTCORFlatFileStorage+Promises.h"
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Private/GDTCORLogSourceMetrics.h"
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Private/GDTCORMetrics.h"
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Private/GDTCORMetricsMetadata.h"
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Private/GDTCORStorageMetadata.h"
|
||||
|
||||
@interface GDTCORMetricsController ()
|
||||
/// The underlying storage object where metrics are stored.
|
||||
@property(nonatomic) id<GDTCORStoragePromiseProtocol> storage;
|
||||
|
||||
@end
|
||||
|
||||
@implementation GDTCORMetricsController
|
||||
|
||||
+ (void)load {
|
||||
#if GDT_TEST
|
||||
[[GDTCORRegistrar sharedInstance] registerMetricsController:[self sharedInstance]
|
||||
target:kGDTCORTargetTest];
|
||||
#endif // GDT_TEST
|
||||
// Only the Firelog backend supports metrics collection.
|
||||
[[GDTCORRegistrar sharedInstance] registerMetricsController:[self sharedInstance]
|
||||
target:kGDTCORTargetCSH];
|
||||
[[GDTCORRegistrar sharedInstance] registerMetricsController:[self sharedInstance]
|
||||
target:kGDTCORTargetFLL];
|
||||
}
|
||||
|
||||
+ (instancetype)sharedInstance {
|
||||
static id sharedInstance;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
sharedInstance = [[self alloc] initWithStorage:[GDTCORFlatFileStorage sharedInstance]];
|
||||
});
|
||||
return sharedInstance;
|
||||
}
|
||||
|
||||
- (instancetype)initWithStorage:(id<GDTCORStoragePromiseProtocol>)storage {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_storage = storage;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (nonnull FBLPromise<NSNull *> *)logEventsDroppedForReason:(GDTCOREventDropReason)reason
|
||||
events:(nonnull NSSet<GDTCOREvent *> *)events {
|
||||
// No-op if there are no events to log.
|
||||
if ([events count] == 0) {
|
||||
return [FBLPromise resolvedWith:nil];
|
||||
}
|
||||
|
||||
__auto_type handler = ^GDTCORMetricsMetadata *(GDTCORMetricsMetadata *_Nullable metricsMetadata,
|
||||
NSError *_Nullable fetchError) {
|
||||
GDTCORLogSourceMetrics *logSourceMetrics =
|
||||
[GDTCORLogSourceMetrics metricsWithEvents:[events allObjects] droppedForReason:reason];
|
||||
|
||||
if (metricsMetadata) {
|
||||
GDTCORLogSourceMetrics *updatedLogSourceMetrics = [metricsMetadata.logSourceMetrics
|
||||
logSourceMetricsByMergingWithLogSourceMetrics:logSourceMetrics];
|
||||
|
||||
return [GDTCORMetricsMetadata
|
||||
metadataWithCollectionStartDate:[metricsMetadata collectionStartDate]
|
||||
logSourceMetrics:updatedLogSourceMetrics];
|
||||
} else {
|
||||
// There was an error (e.g. empty storage); `metricsMetadata` is nil.
|
||||
GDTCORLogDebug(@"Error fetching metrics metadata: %@", fetchError);
|
||||
return [GDTCORMetricsMetadata metadataWithCollectionStartDate:[NSDate date]
|
||||
logSourceMetrics:logSourceMetrics];
|
||||
}
|
||||
};
|
||||
|
||||
return [_storage fetchAndUpdateMetricsWithHandler:handler];
|
||||
}
|
||||
|
||||
- (nonnull FBLPromise<GDTCORMetrics *> *)getAndResetMetrics {
|
||||
__block GDTCORMetricsMetadata *_Nullable snapshottedMetricsMetadata = nil;
|
||||
|
||||
__auto_type handler = ^GDTCORMetricsMetadata *(GDTCORMetricsMetadata *_Nullable metricsMetadata,
|
||||
NSError *_Nullable fetchError) {
|
||||
if (metricsMetadata) {
|
||||
snapshottedMetricsMetadata = metricsMetadata;
|
||||
} else {
|
||||
GDTCORLogDebug(@"Error fetching metrics metadata: %@", fetchError);
|
||||
}
|
||||
return [GDTCORMetricsMetadata metadataWithCollectionStartDate:[NSDate date]
|
||||
logSourceMetrics:[GDTCORLogSourceMetrics metrics]];
|
||||
};
|
||||
|
||||
return [_storage fetchAndUpdateMetricsWithHandler:handler]
|
||||
.validate(^BOOL(NSNull *__unused _) {
|
||||
// Break and reject the promise chain when storage contains no metrics
|
||||
// metadata.
|
||||
return snapshottedMetricsMetadata != nil;
|
||||
})
|
||||
.then(^FBLPromise *(NSNull *__unused _) {
|
||||
// Fetch and return storage metadata (needed for metrics).
|
||||
return [self.storage fetchStorageMetadata];
|
||||
})
|
||||
.then(^GDTCORMetrics *(GDTCORStorageMetadata *storageMetadata) {
|
||||
// Use the fetched metrics & storage metadata to create and return a
|
||||
// complete metrics object.
|
||||
return [GDTCORMetrics metricsWithMetricsMetadata:snapshottedMetricsMetadata
|
||||
storageMetadata:storageMetadata];
|
||||
});
|
||||
}
|
||||
|
||||
- (nonnull FBLPromise<NSNull *> *)offerMetrics:(nonnull GDTCORMetrics *)metrics {
|
||||
// No-op if there are no metrics to offer.
|
||||
if (metrics == nil) {
|
||||
return [FBLPromise resolvedWith:nil];
|
||||
}
|
||||
|
||||
__auto_type handler = ^GDTCORMetricsMetadata *(GDTCORMetricsMetadata *_Nullable metricsMetadata,
|
||||
NSError *_Nullable fetchError) {
|
||||
if (metricsMetadata) {
|
||||
if (metrics.collectionStartDate.timeIntervalSince1970 <=
|
||||
metricsMetadata.collectionStartDate.timeIntervalSince1970) {
|
||||
// If the metrics to append are older than the metrics represented by
|
||||
// the currently stored metrics, then return a new metadata object that
|
||||
// incorporates the data from the given metrics.
|
||||
return [GDTCORMetricsMetadata
|
||||
metadataWithCollectionStartDate:[metrics collectionStartDate]
|
||||
logSourceMetrics:[metricsMetadata.logSourceMetrics
|
||||
logSourceMetricsByMergingWithLogSourceMetrics:
|
||||
metrics.logSourceMetrics]];
|
||||
} else {
|
||||
// This catches an edge case where the given metrics to append are
|
||||
// newer than metrics represented by the currently stored metrics
|
||||
// metadata. In this case, return the existing metadata object as the
|
||||
// given metrics are assumed to already be accounted for by the
|
||||
// currently stored metadata.
|
||||
return metricsMetadata;
|
||||
}
|
||||
} else {
|
||||
// There was an error (e.g. empty storage); `metricsMetadata` is nil.
|
||||
GDTCORLogDebug(@"Error fetching metrics metadata: %@", fetchError);
|
||||
|
||||
NSDate *now = [NSDate date];
|
||||
if (metrics.collectionStartDate.timeIntervalSince1970 <= now.timeIntervalSince1970) {
|
||||
// The given metrics are were recorded up until now. They wouldn't
|
||||
// be offered if they were successfully uploaded so their
|
||||
// corresponding metadata can be safely placed back in storage.
|
||||
return [GDTCORMetricsMetadata metadataWithCollectionStartDate:metrics.collectionStartDate
|
||||
logSourceMetrics:metrics.logSourceMetrics];
|
||||
} else {
|
||||
// This catches an edge case where the given metrics are from the
|
||||
// future. If this occurs, ignore them and store an empty metadata
|
||||
// object intended to track metrics metadata from this time forward.
|
||||
return [GDTCORMetricsMetadata
|
||||
metadataWithCollectionStartDate:[NSDate date]
|
||||
logSourceMetrics:[GDTCORLogSourceMetrics metrics]];
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return [_storage fetchAndUpdateMetricsWithHandler:handler];
|
||||
}
|
||||
|
||||
#pragma mark - GDTCORStorageDelegate
|
||||
|
||||
- (void)storage:(id<GDTCORStorageProtocol>)storage
|
||||
didRemoveExpiredEvents:(nonnull NSSet<GDTCOREvent *> *)events {
|
||||
[self logEventsDroppedForReason:GDTCOREventDropReasonMessageTooOld events:events];
|
||||
}
|
||||
|
||||
- (void)storage:(nonnull id<GDTCORStorageProtocol>)storage
|
||||
didDropEvent:(nonnull GDTCOREvent *)event {
|
||||
[self logEventsDroppedForReason:GDTCOREventDropReasonStorageFull
|
||||
events:[NSSet setWithObject:event]];
|
||||
}
|
||||
|
||||
@end
|
||||
96
Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORMetricsMetadata.m
generated
Normal file
96
Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORMetricsMetadata.m
generated
Normal file
@ -0,0 +1,96 @@
|
||||
// Copyright 2022 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Private/GDTCORMetricsMetadata.h"
|
||||
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Private/GDTCORLogSourceMetrics.h"
|
||||
|
||||
static NSString *const kCollectionStartDate = @"collectionStartDate";
|
||||
static NSString *const kLogSourceMetrics = @"logSourceMetrics";
|
||||
|
||||
@implementation GDTCORMetricsMetadata
|
||||
|
||||
+ (instancetype)metadataWithCollectionStartDate:(NSDate *)collectedSinceDate
|
||||
logSourceMetrics:(GDTCORLogSourceMetrics *)logSourceMetrics {
|
||||
return [[self alloc] initWithCollectionStartDate:collectedSinceDate
|
||||
logSourceMetrics:logSourceMetrics];
|
||||
}
|
||||
|
||||
- (instancetype)initWithCollectionStartDate:(NSDate *)collectionStartDate
|
||||
logSourceMetrics:(GDTCORLogSourceMetrics *)logSourceMetrics {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_collectionStartDate = [collectionStartDate copy];
|
||||
_logSourceMetrics = logSourceMetrics;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
#pragma mark - Equality
|
||||
|
||||
- (BOOL)isEqualToMetricsMetadata:(GDTCORMetricsMetadata *)otherMetricsMetadata {
|
||||
return [self.collectionStartDate isEqualToDate:otherMetricsMetadata.collectionStartDate] &&
|
||||
[self.logSourceMetrics isEqualToLogSourceMetrics:otherMetricsMetadata.logSourceMetrics];
|
||||
}
|
||||
|
||||
- (BOOL)isEqual:(nullable id)object {
|
||||
if (object == nil) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
if (self == object) {
|
||||
return YES;
|
||||
}
|
||||
|
||||
if (![object isKindOfClass:[self class]]) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
return [self isEqualToMetricsMetadata:(GDTCORMetricsMetadata *)object];
|
||||
}
|
||||
|
||||
- (NSUInteger)hash {
|
||||
return [self.collectionStartDate hash] ^ [self.logSourceMetrics hash];
|
||||
}
|
||||
|
||||
#pragma mark - NSSecureCoding
|
||||
|
||||
+ (BOOL)supportsSecureCoding {
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (nullable instancetype)initWithCoder:(nonnull NSCoder *)coder {
|
||||
NSDate *collectionStartDate = [coder decodeObjectOfClass:[NSDate class]
|
||||
forKey:kCollectionStartDate];
|
||||
GDTCORLogSourceMetrics *logSourceMetrics =
|
||||
[coder decodeObjectOfClass:[GDTCORLogSourceMetrics class] forKey:kLogSourceMetrics];
|
||||
|
||||
if (!collectionStartDate || !logSourceMetrics ||
|
||||
![collectionStartDate isKindOfClass:[NSDate class]] ||
|
||||
![logSourceMetrics isKindOfClass:[GDTCORLogSourceMetrics class]]) {
|
||||
// If any of the fields are corrupted, the initializer should fail.
|
||||
return nil;
|
||||
}
|
||||
|
||||
return [self initWithCollectionStartDate:collectionStartDate logSourceMetrics:logSourceMetrics];
|
||||
}
|
||||
|
||||
- (void)encodeWithCoder:(nonnull NSCoder *)coder {
|
||||
[coder encodeObject:self.collectionStartDate forKey:kCollectionStartDate];
|
||||
[coder encodeObject:self.logSourceMetrics forKey:kLogSourceMetrics];
|
||||
}
|
||||
|
||||
@end
|
||||
566
Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORPlatform.m
generated
Normal file
566
Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORPlatform.m
generated
Normal file
@ -0,0 +1,566 @@
|
||||
/*
|
||||
* Copyright 2019 Google
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Internal/GDTCORPlatform.h"
|
||||
|
||||
#import <sys/sysctl.h>
|
||||
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Internal/GDTCORAssert.h"
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Internal/GDTCORReachability.h"
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORConsoleLogger.h"
|
||||
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Private/GDTCORRegistrar_Private.h"
|
||||
|
||||
#ifdef GDTCOR_VERSION
|
||||
#define STR(x) STR_EXPAND(x)
|
||||
#define STR_EXPAND(x) #x
|
||||
NSString *const kGDTCORVersion = @STR(GDTCOR_VERSION);
|
||||
#else
|
||||
NSString *const kGDTCORVersion = @"Unknown";
|
||||
#endif // GDTCOR_VERSION
|
||||
|
||||
const GDTCORBackgroundIdentifier GDTCORBackgroundIdentifierInvalid = 0;
|
||||
|
||||
NSString *const kGDTCORApplicationDidEnterBackgroundNotification =
|
||||
@"GDTCORApplicationDidEnterBackgroundNotification";
|
||||
|
||||
NSString *const kGDTCORApplicationWillEnterForegroundNotification =
|
||||
@"GDTCORApplicationWillEnterForegroundNotification";
|
||||
|
||||
NSString *const kGDTCORApplicationWillTerminateNotification =
|
||||
@"GDTCORApplicationWillTerminateNotification";
|
||||
|
||||
NSURL *GDTCORRootDirectory(void) {
|
||||
static NSURL *GDTPath;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
NSString *cachePath =
|
||||
NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES)[0];
|
||||
GDTPath =
|
||||
[NSURL fileURLWithPath:[NSString stringWithFormat:@"%@/google-sdks-events", cachePath]];
|
||||
GDTCORLogDebug(@"GDT's state will be saved to: %@", GDTPath);
|
||||
});
|
||||
NSError *error;
|
||||
[[NSFileManager defaultManager] createDirectoryAtPath:GDTPath.path
|
||||
withIntermediateDirectories:YES
|
||||
attributes:nil
|
||||
error:&error];
|
||||
GDTCORAssert(error == nil, @"There was an error creating GDT's path");
|
||||
return GDTPath;
|
||||
}
|
||||
|
||||
BOOL GDTCORReachabilityFlagsReachable(GDTCORNetworkReachabilityFlags flags) {
|
||||
#if !TARGET_OS_WATCH
|
||||
BOOL reachable =
|
||||
(flags & kSCNetworkReachabilityFlagsReachable) == kSCNetworkReachabilityFlagsReachable;
|
||||
BOOL connectionRequired = (flags & kSCNetworkReachabilityFlagsConnectionRequired) ==
|
||||
kSCNetworkReachabilityFlagsConnectionRequired;
|
||||
return reachable && !connectionRequired;
|
||||
#else
|
||||
return (flags & kGDTCORNetworkReachabilityFlagsReachable) ==
|
||||
kGDTCORNetworkReachabilityFlagsReachable;
|
||||
#endif
|
||||
}
|
||||
|
||||
BOOL GDTCORReachabilityFlagsContainWWAN(GDTCORNetworkReachabilityFlags flags) {
|
||||
#if TARGET_OS_IOS
|
||||
return (flags & kSCNetworkReachabilityFlagsIsWWAN) == kSCNetworkReachabilityFlagsIsWWAN;
|
||||
#else
|
||||
// Assume network connection not WWAN on macOS, tvOS, watchOS.
|
||||
return NO;
|
||||
#endif // TARGET_OS_IOS
|
||||
}
|
||||
|
||||
GDTCORNetworkType GDTCORNetworkTypeMessage(void) {
|
||||
#if !TARGET_OS_WATCH
|
||||
SCNetworkReachabilityFlags reachabilityFlags = [GDTCORReachability currentFlags];
|
||||
if ((reachabilityFlags & kSCNetworkReachabilityFlagsReachable) ==
|
||||
kSCNetworkReachabilityFlagsReachable) {
|
||||
if (GDTCORReachabilityFlagsContainWWAN(reachabilityFlags)) {
|
||||
return GDTCORNetworkTypeMobile;
|
||||
} else {
|
||||
return GDTCORNetworkTypeWIFI;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return GDTCORNetworkTypeUNKNOWN;
|
||||
}
|
||||
|
||||
GDTCORNetworkMobileSubtype GDTCORNetworkMobileSubTypeMessage(void) {
|
||||
// TODO(Xcode 15): When Xcode 15 is the minimum supported Xcode version,
|
||||
// it will be unnecessary to check if `TARGET_OS_VISION` is defined.
|
||||
#if TARGET_OS_IOS && (!defined(TARGET_OS_VISION) || !TARGET_OS_VISION)
|
||||
static NSDictionary<NSString *, NSNumber *> *CTRadioAccessTechnologyToNetworkSubTypeMessage;
|
||||
static CTTelephonyNetworkInfo *networkInfo;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
CTRadioAccessTechnologyToNetworkSubTypeMessage = @{
|
||||
CTRadioAccessTechnologyGPRS : @(GDTCORNetworkMobileSubtypeGPRS),
|
||||
CTRadioAccessTechnologyEdge : @(GDTCORNetworkMobileSubtypeEdge),
|
||||
CTRadioAccessTechnologyWCDMA : @(GDTCORNetworkMobileSubtypeWCDMA),
|
||||
CTRadioAccessTechnologyHSDPA : @(GDTCORNetworkMobileSubtypeHSDPA),
|
||||
CTRadioAccessTechnologyHSUPA : @(GDTCORNetworkMobileSubtypeHSUPA),
|
||||
CTRadioAccessTechnologyCDMA1x : @(GDTCORNetworkMobileSubtypeCDMA1x),
|
||||
CTRadioAccessTechnologyCDMAEVDORev0 : @(GDTCORNetworkMobileSubtypeCDMAEVDORev0),
|
||||
CTRadioAccessTechnologyCDMAEVDORevA : @(GDTCORNetworkMobileSubtypeCDMAEVDORevA),
|
||||
CTRadioAccessTechnologyCDMAEVDORevB : @(GDTCORNetworkMobileSubtypeCDMAEVDORevB),
|
||||
CTRadioAccessTechnologyeHRPD : @(GDTCORNetworkMobileSubtypeHRPD),
|
||||
CTRadioAccessTechnologyLTE : @(GDTCORNetworkMobileSubtypeLTE),
|
||||
};
|
||||
networkInfo = [[CTTelephonyNetworkInfo alloc] init];
|
||||
});
|
||||
NSString *networkCurrentRadioAccessTechnology;
|
||||
#if TARGET_OS_MACCATALYST
|
||||
NSDictionary<NSString *, NSString *> *networkCurrentRadioAccessTechnologyDict =
|
||||
networkInfo.serviceCurrentRadioAccessTechnology;
|
||||
if (networkCurrentRadioAccessTechnologyDict.count) {
|
||||
networkCurrentRadioAccessTechnology = networkCurrentRadioAccessTechnologyDict.allValues[0];
|
||||
}
|
||||
#else // TARGET_OS_MACCATALYST
|
||||
NSDictionary<NSString *, NSString *> *networkCurrentRadioAccessTechnologyDict =
|
||||
networkInfo.serviceCurrentRadioAccessTechnology;
|
||||
if (networkCurrentRadioAccessTechnologyDict.count) {
|
||||
// In iOS 12, multiple radio technologies can be captured. We prefer not particular radio
|
||||
// tech to another, so we'll just return the first value in the dictionary.
|
||||
networkCurrentRadioAccessTechnology = networkCurrentRadioAccessTechnologyDict.allValues[0];
|
||||
}
|
||||
#endif // TARGET_OS_MACCATALYST
|
||||
if (networkCurrentRadioAccessTechnology) {
|
||||
NSNumber *networkMobileSubtype =
|
||||
CTRadioAccessTechnologyToNetworkSubTypeMessage[networkCurrentRadioAccessTechnology];
|
||||
return networkMobileSubtype.intValue;
|
||||
} else {
|
||||
return GDTCORNetworkMobileSubtypeUNKNOWN;
|
||||
}
|
||||
#else // TARGET_OS_IOS && (!defined(TARGET_OS_VISION) || !TARGET_OS_VISION)
|
||||
return GDTCORNetworkMobileSubtypeUNKNOWN;
|
||||
#endif // TARGET_OS_IOS && (!defined(TARGET_OS_VISION) || !TARGET_OS_VISION)
|
||||
}
|
||||
|
||||
NSString *_Nonnull GDTCORDeviceModel(void) {
|
||||
static NSString *deviceModel = @"Unknown";
|
||||
|
||||
#if TARGET_OS_IOS || TARGET_OS_TV
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
size_t size;
|
||||
char *keyToExtract = "hw.machine";
|
||||
sysctlbyname(keyToExtract, NULL, &size, NULL, 0);
|
||||
if (size > 0) {
|
||||
char *machine = calloc(1, size);
|
||||
sysctlbyname(keyToExtract, machine, &size, NULL, 0);
|
||||
deviceModel = [NSString stringWithCString:machine encoding:NSUTF8StringEncoding];
|
||||
free(machine);
|
||||
} else {
|
||||
deviceModel = [UIDevice currentDevice].model;
|
||||
}
|
||||
});
|
||||
#endif
|
||||
|
||||
return deviceModel;
|
||||
}
|
||||
|
||||
NSData *_Nullable GDTCOREncodeArchive(id<NSSecureCoding> obj,
|
||||
NSString *filePath,
|
||||
NSError *_Nullable *error) {
|
||||
BOOL result = NO;
|
||||
if (filePath.length > 0) {
|
||||
// TODO(ncooke3): For future cleanup– this API shouldn't touch the file
|
||||
// system unless it successfully encoded the given object.
|
||||
result = [[NSFileManager defaultManager]
|
||||
createDirectoryAtPath:[filePath stringByDeletingLastPathComponent]
|
||||
withIntermediateDirectories:YES
|
||||
attributes:nil
|
||||
error:error];
|
||||
if (result == NO || *error) {
|
||||
GDTCORLogDebug(@"Attempt to create directory failed: path:%@ error:%@", filePath, *error);
|
||||
return nil;
|
||||
}
|
||||
}
|
||||
NSData *resultData;
|
||||
resultData = [NSKeyedArchiver archivedDataWithRootObject:obj
|
||||
requiringSecureCoding:YES
|
||||
error:error];
|
||||
if (resultData == nil || (error != NULL && *error != nil)) {
|
||||
GDTCORLogDebug(@"Encoding an object failed: %@", *error);
|
||||
return nil;
|
||||
}
|
||||
if (filePath.length > 0) {
|
||||
result = [resultData writeToFile:filePath options:NSDataWritingAtomic error:error];
|
||||
if (result == NO || (error != NULL && *error != nil)) {
|
||||
if (error != NULL && *error != nil) {
|
||||
GDTCORLogDebug(@"Attempt to write archive failed: path:%@ error:%@", filePath, *error);
|
||||
} else {
|
||||
GDTCORLogDebug(@"Attempt to write archive failed: path:%@", filePath);
|
||||
}
|
||||
} else {
|
||||
GDTCORLogDebug(@"Writing archive succeeded: %@", filePath);
|
||||
}
|
||||
}
|
||||
return resultData;
|
||||
}
|
||||
|
||||
id<NSSecureCoding> _Nullable GDTCORDecodeArchiveAtPath(Class archiveClass,
|
||||
NSString *_Nonnull archivePath,
|
||||
NSError **_Nonnull error) {
|
||||
NSData *data = [NSData dataWithContentsOfFile:archivePath options:0 error:error];
|
||||
if (data == nil) {
|
||||
// Reading the file failed and `error` will be populated.
|
||||
return nil;
|
||||
}
|
||||
|
||||
return GDTCORDecodeArchive(archiveClass, data, error);
|
||||
}
|
||||
|
||||
id<NSSecureCoding> _Nullable GDTCORDecodeArchive(Class archiveClass,
|
||||
NSData *_Nonnull archiveData,
|
||||
NSError **_Nonnull error) {
|
||||
return [NSKeyedUnarchiver unarchivedObjectOfClass:archiveClass fromData:archiveData error:error];
|
||||
}
|
||||
|
||||
BOOL GDTCORWriteDataToFile(NSData *data, NSString *filePath, NSError *_Nullable *outError) {
|
||||
BOOL result = NO;
|
||||
if (filePath.length > 0) {
|
||||
result = [[NSFileManager defaultManager]
|
||||
createDirectoryAtPath:[filePath stringByDeletingLastPathComponent]
|
||||
withIntermediateDirectories:YES
|
||||
attributes:nil
|
||||
error:outError];
|
||||
if (result == NO || *outError) {
|
||||
GDTCORLogDebug(@"Attempt to create directory failed: path:%@ error:%@", filePath, *outError);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
if (filePath.length > 0) {
|
||||
result = [data writeToFile:filePath options:NSDataWritingAtomic error:outError];
|
||||
if (result == NO || *outError) {
|
||||
GDTCORLogDebug(@"Attempt to write archive failed: path:%@ error:%@", filePath, *outError);
|
||||
} else {
|
||||
GDTCORLogDebug(@"Writing archive succeeded: %@", filePath);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@interface GDTCORApplication ()
|
||||
/**
|
||||
Private flag to match the existing `readonly` public flag. This will be accurate for all platforms,
|
||||
since we handle each platform's lifecycle notifications separately.
|
||||
*/
|
||||
@property(atomic, readwrite) BOOL isRunningInBackground;
|
||||
|
||||
@end
|
||||
|
||||
@implementation GDTCORApplication
|
||||
|
||||
#if TARGET_OS_WATCH
|
||||
/** A dispatch queue on which all task semaphores will populate and remove from
|
||||
* gBackgroundIdentifierToSemaphoreMap.
|
||||
*/
|
||||
static dispatch_queue_t gSemaphoreQueue;
|
||||
|
||||
/** For mapping backgroundIdentifier to task semaphore. */
|
||||
static NSMutableDictionary<NSNumber *, dispatch_semaphore_t> *gBackgroundIdentifierToSemaphoreMap;
|
||||
#endif
|
||||
|
||||
+ (void)load {
|
||||
GDTCORLogDebug(
|
||||
@"%@", @"GDT is initializing. Please note that if you quit the app via the "
|
||||
"debugger and not through a lifecycle event, event data will remain on disk but "
|
||||
"storage won't have a reference to them since the singleton wasn't saved to disk.");
|
||||
#if TARGET_OS_IOS || TARGET_OS_TV
|
||||
// If this asserts, please file a bug at https://github.com/firebase/firebase-ios-sdk/issues.
|
||||
GDTCORFatalAssert(
|
||||
GDTCORBackgroundIdentifierInvalid == UIBackgroundTaskInvalid,
|
||||
@"GDTCORBackgroundIdentifierInvalid and UIBackgroundTaskInvalid should be the same.");
|
||||
#endif
|
||||
[self sharedApplication];
|
||||
}
|
||||
|
||||
+ (void)initialize {
|
||||
#if TARGET_OS_WATCH
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
gSemaphoreQueue = dispatch_queue_create("com.google.GDTCORApplication", DISPATCH_QUEUE_SERIAL);
|
||||
GDTCORLogDebug(
|
||||
@"%@",
|
||||
@"GDTCORApplication is initializing on watchOS, gSemaphoreQueue has been initialized.");
|
||||
gBackgroundIdentifierToSemaphoreMap = [[NSMutableDictionary alloc] init];
|
||||
GDTCORLogDebug(@"%@", @"GDTCORApplication is initializing on watchOS, "
|
||||
@"gBackgroundIdentifierToSemaphoreMap has been initialized.");
|
||||
});
|
||||
#endif
|
||||
}
|
||||
|
||||
+ (nullable GDTCORApplication *)sharedApplication {
|
||||
static GDTCORApplication *application;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
application = [[GDTCORApplication alloc] init];
|
||||
});
|
||||
return application;
|
||||
}
|
||||
|
||||
- (instancetype)init {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
// This class will be instantiated in the foreground.
|
||||
_isRunningInBackground = NO;
|
||||
|
||||
#if TARGET_OS_IOS || TARGET_OS_TV
|
||||
NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
|
||||
[notificationCenter addObserver:self
|
||||
selector:@selector(iOSApplicationDidEnterBackground:)
|
||||
name:UIApplicationDidEnterBackgroundNotification
|
||||
object:nil];
|
||||
[notificationCenter addObserver:self
|
||||
selector:@selector(iOSApplicationWillEnterForeground:)
|
||||
name:UIApplicationWillEnterForegroundNotification
|
||||
object:nil];
|
||||
|
||||
NSString *name = UIApplicationWillTerminateNotification;
|
||||
[notificationCenter addObserver:self
|
||||
selector:@selector(iOSApplicationWillTerminate:)
|
||||
name:name
|
||||
object:nil];
|
||||
|
||||
#if defined(__IPHONE_13_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 130000
|
||||
if (@available(iOS 13, tvOS 13.0, *)) {
|
||||
[notificationCenter addObserver:self
|
||||
selector:@selector(iOSApplicationWillEnterForeground:)
|
||||
name:UISceneWillEnterForegroundNotification
|
||||
object:nil];
|
||||
[notificationCenter addObserver:self
|
||||
selector:@selector(iOSApplicationDidEnterBackground:)
|
||||
name:UISceneWillDeactivateNotification
|
||||
object:nil];
|
||||
}
|
||||
#endif // defined(__IPHONE_13_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 130000
|
||||
|
||||
#elif TARGET_OS_OSX
|
||||
NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
|
||||
[notificationCenter addObserver:self
|
||||
selector:@selector(macOSApplicationWillTerminate:)
|
||||
name:NSApplicationWillTerminateNotification
|
||||
object:nil];
|
||||
|
||||
#elif TARGET_OS_WATCH
|
||||
// TODO: Notification on watchOS platform is currently posted by strings which are frangible.
|
||||
// TODO: Needs improvements here.
|
||||
NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
|
||||
[notificationCenter addObserver:self
|
||||
selector:@selector(iOSApplicationDidEnterBackground:)
|
||||
name:@"UIApplicationDidEnterBackgroundNotification"
|
||||
object:nil];
|
||||
[notificationCenter addObserver:self
|
||||
selector:@selector(iOSApplicationWillEnterForeground:)
|
||||
name:@"UIApplicationWillEnterForegroundNotification"
|
||||
object:nil];
|
||||
|
||||
// Adds observers for app extension on watchOS platform
|
||||
[notificationCenter addObserver:self
|
||||
selector:@selector(iOSApplicationDidEnterBackground:)
|
||||
name:NSExtensionHostDidEnterBackgroundNotification
|
||||
object:nil];
|
||||
[notificationCenter addObserver:self
|
||||
selector:@selector(iOSApplicationWillEnterForeground:)
|
||||
name:NSExtensionHostWillEnterForegroundNotification
|
||||
object:nil];
|
||||
#endif
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
#if TARGET_OS_WATCH
|
||||
/** Generates and maps a unique background identifier to the given semaphore.
|
||||
*
|
||||
* @param semaphore The semaphore to map.
|
||||
* @return A unique GDTCORBackgroundIdentifier mapped to the given semaphore.
|
||||
*/
|
||||
+ (GDTCORBackgroundIdentifier)createAndMapBackgroundIdentifierToSemaphore:
|
||||
(dispatch_semaphore_t)semaphore {
|
||||
__block GDTCORBackgroundIdentifier bgID = GDTCORBackgroundIdentifierInvalid;
|
||||
dispatch_queue_t queue = gSemaphoreQueue;
|
||||
NSMutableDictionary<NSNumber *, dispatch_semaphore_t> *map = gBackgroundIdentifierToSemaphoreMap;
|
||||
if (queue && map) {
|
||||
dispatch_sync(queue, ^{
|
||||
bgID = arc4random();
|
||||
NSNumber *bgIDNumber = @(bgID);
|
||||
while (bgID == GDTCORBackgroundIdentifierInvalid || map[bgIDNumber]) {
|
||||
bgID = arc4random();
|
||||
bgIDNumber = @(bgID);
|
||||
}
|
||||
map[bgIDNumber] = semaphore;
|
||||
});
|
||||
}
|
||||
return bgID;
|
||||
}
|
||||
|
||||
/** Returns the semaphore mapped to given bgID and removes the value from the map.
|
||||
*
|
||||
* @param bgID The unique NSUInteger as GDTCORBackgroundIdentifier.
|
||||
* @return The semaphore mapped by given bgID.
|
||||
*/
|
||||
+ (dispatch_semaphore_t)semaphoreForBackgroundIdentifier:(GDTCORBackgroundIdentifier)bgID {
|
||||
__block dispatch_semaphore_t semaphore;
|
||||
dispatch_queue_t queue = gSemaphoreQueue;
|
||||
NSMutableDictionary<NSNumber *, dispatch_semaphore_t> *map = gBackgroundIdentifierToSemaphoreMap;
|
||||
NSNumber *bgIDNumber = @(bgID);
|
||||
if (queue && map) {
|
||||
dispatch_sync(queue, ^{
|
||||
semaphore = map[bgIDNumber];
|
||||
[map removeObjectForKey:bgIDNumber];
|
||||
});
|
||||
}
|
||||
return semaphore;
|
||||
}
|
||||
#endif
|
||||
|
||||
- (GDTCORBackgroundIdentifier)beginBackgroundTaskWithName:(NSString *)name
|
||||
expirationHandler:(void (^)(void))handler {
|
||||
__block GDTCORBackgroundIdentifier bgID = GDTCORBackgroundIdentifierInvalid;
|
||||
#if !TARGET_OS_WATCH
|
||||
bgID = [[self sharedApplicationForBackgroundTask] beginBackgroundTaskWithName:name
|
||||
expirationHandler:handler];
|
||||
#if !NDEBUG
|
||||
if (bgID != GDTCORBackgroundIdentifierInvalid) {
|
||||
GDTCORLogDebug(@"Creating background task with name:%@ bgID:%ld", name, (long)bgID);
|
||||
}
|
||||
#endif // !NDEBUG
|
||||
#elif TARGET_OS_WATCH
|
||||
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
|
||||
bgID = [GDTCORApplication createAndMapBackgroundIdentifierToSemaphore:semaphore];
|
||||
if (bgID != GDTCORBackgroundIdentifierInvalid) {
|
||||
GDTCORLogDebug(@"Creating activity with name:%@ bgID:%ld on watchOS.", name, (long)bgID);
|
||||
}
|
||||
[[self sharedNSProcessInfoForBackgroundTask]
|
||||
performExpiringActivityWithReason:name
|
||||
usingBlock:^(BOOL expired) {
|
||||
if (expired) {
|
||||
if (handler) {
|
||||
handler();
|
||||
}
|
||||
dispatch_semaphore_signal(semaphore);
|
||||
GDTCORLogDebug(
|
||||
@"Activity with name:%@ bgID:%ld on watchOS is expiring.",
|
||||
name, (long)bgID);
|
||||
} else {
|
||||
dispatch_semaphore_wait(
|
||||
semaphore,
|
||||
dispatch_time(DISPATCH_TIME_NOW, 30 * NSEC_PER_SEC));
|
||||
}
|
||||
}];
|
||||
#endif
|
||||
return bgID;
|
||||
}
|
||||
|
||||
- (void)endBackgroundTask:(GDTCORBackgroundIdentifier)bgID {
|
||||
#if !TARGET_OS_WATCH
|
||||
if (bgID != GDTCORBackgroundIdentifierInvalid) {
|
||||
GDTCORLogDebug(@"Ending background task with ID:%ld was successful", (long)bgID);
|
||||
[[self sharedApplicationForBackgroundTask] endBackgroundTask:bgID];
|
||||
return;
|
||||
}
|
||||
#elif TARGET_OS_WATCH
|
||||
if (bgID != GDTCORBackgroundIdentifierInvalid) {
|
||||
dispatch_semaphore_t semaphore = [GDTCORApplication semaphoreForBackgroundIdentifier:bgID];
|
||||
GDTCORLogDebug(@"Ending activity with bgID:%ld on watchOS.", (long)bgID);
|
||||
if (semaphore) {
|
||||
dispatch_semaphore_signal(semaphore);
|
||||
GDTCORLogDebug(@"Signaling semaphore with bgID:%ld on watchOS.", (long)bgID);
|
||||
} else {
|
||||
GDTCORLogDebug(@"Semaphore with bgID:%ld is nil on watchOS.", (long)bgID);
|
||||
}
|
||||
}
|
||||
#endif // !TARGET_OS_WATCH
|
||||
}
|
||||
|
||||
#pragma mark - App environment helpers
|
||||
|
||||
- (BOOL)isAppExtension {
|
||||
BOOL appExtension = [[[NSBundle mainBundle] bundlePath] hasSuffix:@".appex"];
|
||||
return appExtension;
|
||||
}
|
||||
|
||||
/** Returns a UIApplication or NSProcessInfo instance if on the appropriate platform.
|
||||
*
|
||||
* @return The shared UIApplication or NSProcessInfo if on the appropriate platform.
|
||||
*/
|
||||
#if TARGET_OS_IOS || TARGET_OS_TV
|
||||
- (nullable UIApplication *)sharedApplicationForBackgroundTask {
|
||||
#elif TARGET_OS_WATCH
|
||||
- (nullable NSProcessInfo *)sharedNSProcessInfoForBackgroundTask {
|
||||
#else
|
||||
- (nullable id)sharedApplicationForBackgroundTask {
|
||||
#endif
|
||||
id sharedInstance = nil;
|
||||
#if TARGET_OS_IOS || TARGET_OS_TV
|
||||
if (![self isAppExtension]) {
|
||||
Class uiApplicationClass = NSClassFromString(@"UIApplication");
|
||||
if (uiApplicationClass &&
|
||||
[uiApplicationClass respondsToSelector:(NSSelectorFromString(@"sharedApplication"))]) {
|
||||
sharedInstance = [uiApplicationClass sharedApplication];
|
||||
}
|
||||
}
|
||||
#elif TARGET_OS_WATCH
|
||||
sharedInstance = [NSProcessInfo processInfo];
|
||||
#endif
|
||||
return sharedInstance;
|
||||
}
|
||||
|
||||
#pragma mark - UIApplicationDelegate and WKExtensionDelegate
|
||||
|
||||
#if TARGET_OS_IOS || TARGET_OS_TV || TARGET_OS_WATCH
|
||||
- (void)iOSApplicationDidEnterBackground:(NSNotification *)notif {
|
||||
_isRunningInBackground = YES;
|
||||
|
||||
NSNotificationCenter *notifCenter = [NSNotificationCenter defaultCenter];
|
||||
GDTCORLogDebug(@"%@", @"GDTCORPlatform is sending a notif that the app is backgrounding.");
|
||||
[notifCenter postNotificationName:kGDTCORApplicationDidEnterBackgroundNotification object:nil];
|
||||
}
|
||||
|
||||
- (void)iOSApplicationWillEnterForeground:(NSNotification *)notif {
|
||||
_isRunningInBackground = NO;
|
||||
|
||||
NSNotificationCenter *notifCenter = [NSNotificationCenter defaultCenter];
|
||||
GDTCORLogDebug(@"%@", @"GDTCORPlatform is sending a notif that the app is foregrounding.");
|
||||
[notifCenter postNotificationName:kGDTCORApplicationWillEnterForegroundNotification object:nil];
|
||||
}
|
||||
#endif // TARGET_OS_IOS || TARGET_OS_TV || TARGET_OS_WATCH
|
||||
|
||||
#pragma mark - UIApplicationDelegate
|
||||
|
||||
#if TARGET_OS_IOS || TARGET_OS_TV
|
||||
- (void)iOSApplicationWillTerminate:(NSNotification *)notif {
|
||||
NSNotificationCenter *notifCenter = [NSNotificationCenter defaultCenter];
|
||||
GDTCORLogDebug(@"%@", @"GDTCORPlatform is sending a notif that the app is terminating.");
|
||||
[notifCenter postNotificationName:kGDTCORApplicationWillTerminateNotification object:nil];
|
||||
}
|
||||
#endif // TARGET_OS_IOS || TARGET_OS_TV
|
||||
|
||||
#pragma mark - NSApplicationDelegate
|
||||
|
||||
#if TARGET_OS_OSX
|
||||
- (void)macOSApplicationWillTerminate:(NSNotification *)notif {
|
||||
NSNotificationCenter *notifCenter = [NSNotificationCenter defaultCenter];
|
||||
GDTCORLogDebug(@"%@", @"GDTCORPlatform is sending a notif that the app is terminating.");
|
||||
[notifCenter postNotificationName:kGDTCORApplicationWillTerminateNotification object:nil];
|
||||
}
|
||||
#endif // TARGET_OS_OSX
|
||||
|
||||
@end
|
||||
77
Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORProductData.m
generated
Normal file
77
Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORProductData.m
generated
Normal file
@ -0,0 +1,77 @@
|
||||
// Copyright 2023 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORProductData.h"
|
||||
|
||||
@implementation GDTCORProductData
|
||||
|
||||
- (instancetype)initWithProductID:(int32_t)productID {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_productID = productID;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (nonnull id)copyWithZone:(nullable NSZone *)zone {
|
||||
return [[[self class] alloc] initWithProductID:self.productID];
|
||||
}
|
||||
|
||||
#pragma mark - Equality
|
||||
|
||||
- (BOOL)isEqualToProductData:(GDTCORProductData *)otherProductData {
|
||||
return self.productID == otherProductData.productID;
|
||||
}
|
||||
|
||||
- (BOOL)isEqual:(nullable id)object {
|
||||
if (object == nil) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
if (self == object) {
|
||||
return YES;
|
||||
}
|
||||
|
||||
if (![object isKindOfClass:[self class]]) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
return [self isEqualToProductData:(GDTCORProductData *)object];
|
||||
}
|
||||
|
||||
- (NSUInteger)hash {
|
||||
return self.productID;
|
||||
}
|
||||
|
||||
#pragma mark - NSSecureCoding
|
||||
|
||||
/// NSCoding key for `productID` property.
|
||||
static NSString *kProductIDKey = @"GDTCORProductDataProductIDKey";
|
||||
|
||||
+ (BOOL)supportsSecureCoding {
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (nullable instancetype)initWithCoder:(nonnull NSCoder *)coder {
|
||||
int32_t productID = [coder decodeInt32ForKey:kProductIDKey];
|
||||
return [self initWithProductID:productID];
|
||||
}
|
||||
|
||||
- (void)encodeWithCoder:(nonnull NSCoder *)coder {
|
||||
[coder encodeInt32:self.productID forKey:kProductIDKey];
|
||||
}
|
||||
|
||||
@end
|
||||
125
Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORReachability.m
generated
Normal file
125
Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORReachability.m
generated
Normal file
@ -0,0 +1,125 @@
|
||||
/*
|
||||
* Copyright 2019 Google
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Internal/GDTCORReachability.h"
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Private/GDTCORReachability_Private.h"
|
||||
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORConsoleLogger.h"
|
||||
|
||||
#import <netinet/in.h>
|
||||
|
||||
/** Sets the _callbackFlag ivar whenever the network changes.
|
||||
*
|
||||
* @param reachability The reachability object calling back.
|
||||
* @param flags The new flag values.
|
||||
* @param info Any data that might be passed in by the callback.
|
||||
*/
|
||||
static void GDTCORReachabilityCallback(GDTCORNetworkReachabilityRef reachability,
|
||||
GDTCORNetworkReachabilityFlags flags,
|
||||
void *info);
|
||||
|
||||
@implementation GDTCORReachability {
|
||||
/** The reachability object. */
|
||||
GDTCORNetworkReachabilityRef _reachabilityRef;
|
||||
|
||||
/** The queue on which callbacks and all work will occur. */
|
||||
dispatch_queue_t _reachabilityQueue;
|
||||
|
||||
/** Flags specified by reachability callbacks. */
|
||||
GDTCORNetworkReachabilityFlags _callbackFlags;
|
||||
}
|
||||
|
||||
+ (void)initialize {
|
||||
[self sharedInstance];
|
||||
}
|
||||
|
||||
+ (instancetype)sharedInstance {
|
||||
static GDTCORReachability *sharedInstance;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
sharedInstance = [[GDTCORReachability alloc] init];
|
||||
});
|
||||
return sharedInstance;
|
||||
}
|
||||
|
||||
+ (GDTCORNetworkReachabilityFlags)currentFlags {
|
||||
__block GDTCORNetworkReachabilityFlags currentFlags;
|
||||
#if !TARGET_OS_WATCH
|
||||
dispatch_sync([GDTCORReachability sharedInstance] -> _reachabilityQueue, ^{
|
||||
GDTCORReachability *reachability = [GDTCORReachability sharedInstance];
|
||||
currentFlags =
|
||||
reachability->_callbackFlags ? reachability->_callbackFlags : reachability->_flags;
|
||||
GDTCORLogDebug(@"Initial reachability flags determined: %d", currentFlags);
|
||||
});
|
||||
#else
|
||||
currentFlags = kGDTCORNetworkReachabilityFlagsReachable;
|
||||
#endif
|
||||
return currentFlags;
|
||||
}
|
||||
|
||||
- (instancetype)init {
|
||||
self = [super init];
|
||||
#if !TARGET_OS_WATCH
|
||||
if (self) {
|
||||
struct sockaddr_in zeroAddress;
|
||||
bzero(&zeroAddress, sizeof(zeroAddress));
|
||||
zeroAddress.sin_len = sizeof(zeroAddress);
|
||||
zeroAddress.sin_family = AF_INET;
|
||||
|
||||
_reachabilityQueue =
|
||||
dispatch_queue_create("com.google.GDTCORReachability", DISPATCH_QUEUE_SERIAL);
|
||||
_reachabilityRef = SCNetworkReachabilityCreateWithAddress(
|
||||
kCFAllocatorDefault, (const struct sockaddr *)&zeroAddress);
|
||||
Boolean success = SCNetworkReachabilitySetDispatchQueue(_reachabilityRef, _reachabilityQueue);
|
||||
if (!success) {
|
||||
GDTCORLogWarning(GDTCORMCWReachabilityFailed, @"%@", @"The reachability queue wasn't set.");
|
||||
}
|
||||
success = SCNetworkReachabilitySetCallback(_reachabilityRef, GDTCORReachabilityCallback, NULL);
|
||||
if (!success) {
|
||||
GDTCORLogWarning(GDTCORMCWReachabilityFailed, @"%@",
|
||||
@"The reachability callback wasn't set.");
|
||||
}
|
||||
|
||||
// Get the initial set of flags.
|
||||
dispatch_async(_reachabilityQueue, ^{
|
||||
Boolean valid = SCNetworkReachabilityGetFlags(self->_reachabilityRef, &self->_flags);
|
||||
if (!valid) {
|
||||
GDTCORLogDebug(@"%@", @"Determining reachability failed.");
|
||||
self->_flags = 0;
|
||||
}
|
||||
});
|
||||
}
|
||||
#endif
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)setCallbackFlags:(GDTCORNetworkReachabilityFlags)flags {
|
||||
if (_callbackFlags != flags) {
|
||||
self->_callbackFlags = flags;
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wunused-function"
|
||||
static void GDTCORReachabilityCallback(GDTCORNetworkReachabilityRef reachability,
|
||||
GDTCORNetworkReachabilityFlags flags,
|
||||
void *info) {
|
||||
#pragma clang diagnostic pop
|
||||
GDTCORLogDebug(@"Reachability changed, new flags: %d", flags);
|
||||
[[GDTCORReachability sharedInstance] setCallbackFlags:flags];
|
||||
}
|
||||
194
Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORRegistrar.m
generated
Normal file
194
Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORRegistrar.m
generated
Normal file
@ -0,0 +1,194 @@
|
||||
/*
|
||||
* Copyright 2018 Google
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Internal/GDTCORRegistrar.h"
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Private/GDTCORRegistrar_Private.h"
|
||||
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORConsoleLogger.h"
|
||||
|
||||
id<GDTCORStorageProtocol> _Nullable GDTCORStorageInstanceForTarget(GDTCORTarget target) {
|
||||
return [GDTCORRegistrar sharedInstance].targetToStorage[@(target)];
|
||||
}
|
||||
|
||||
id<GDTCORStoragePromiseProtocol> _Nullable GDTCORStoragePromiseInstanceForTarget(
|
||||
GDTCORTarget target) {
|
||||
id storage = [GDTCORRegistrar sharedInstance].targetToStorage[@(target)];
|
||||
if ([storage conformsToProtocol:@protocol(GDTCORStoragePromiseProtocol)]) {
|
||||
return storage;
|
||||
} else {
|
||||
return nil;
|
||||
}
|
||||
}
|
||||
|
||||
id<GDTCORMetricsControllerProtocol> _Nullable GDTCORMetricsControllerInstanceForTarget(
|
||||
GDTCORTarget target) {
|
||||
return [GDTCORRegistrar sharedInstance].targetToMetricsController[@(target)];
|
||||
}
|
||||
|
||||
@implementation GDTCORRegistrar
|
||||
|
||||
// Manaully synthesize properties declared in `GDTCORRegistrar_Private.h` category.
|
||||
@synthesize targetToUploader = _targetToUploader;
|
||||
@synthesize targetToStorage = _targetToStorage;
|
||||
@synthesize targetToMetricsController = _targetToMetricsController;
|
||||
|
||||
+ (instancetype)sharedInstance {
|
||||
static GDTCORRegistrar *sharedInstance;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
sharedInstance = [[GDTCORRegistrar alloc] init];
|
||||
});
|
||||
return sharedInstance;
|
||||
}
|
||||
|
||||
- (instancetype)init {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_registrarQueue = dispatch_queue_create("com.google.GDTCORRegistrar", DISPATCH_QUEUE_SERIAL);
|
||||
_targetToUploader = [NSMutableDictionary dictionary];
|
||||
_targetToStorage = [NSMutableDictionary dictionary];
|
||||
_targetToMetricsController = [NSMutableDictionary dictionary];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)registerUploader:(id<GDTCORUploader>)backend target:(GDTCORTarget)target {
|
||||
__weak GDTCORRegistrar *weakSelf = self;
|
||||
dispatch_async(_registrarQueue, ^{
|
||||
GDTCORRegistrar *strongSelf = weakSelf;
|
||||
if (strongSelf) {
|
||||
GDTCORLogDebug(@"Registered an uploader: %@ for target:%ld", backend, (long)target);
|
||||
strongSelf->_targetToUploader[@(target)] = backend;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
- (void)registerStorage:(id<GDTCORStorageProtocol>)storage target:(GDTCORTarget)target {
|
||||
__weak GDTCORRegistrar *weakSelf = self;
|
||||
dispatch_async(_registrarQueue, ^{
|
||||
GDTCORRegistrar *strongSelf = weakSelf;
|
||||
if (strongSelf) {
|
||||
GDTCORLogDebug(@"Registered storage: %@ for target:%ld", storage, (long)target);
|
||||
strongSelf->_targetToStorage[@(target)] = storage;
|
||||
[self setMetricsControllerAsStorageDelegateForTarget:target];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
- (void)registerMetricsController:(id<GDTCORMetricsControllerProtocol>)metricsController
|
||||
target:(GDTCORTarget)target {
|
||||
__weak GDTCORRegistrar *weakSelf = self;
|
||||
dispatch_async(_registrarQueue, ^{
|
||||
GDTCORRegistrar *strongSelf = weakSelf;
|
||||
if (strongSelf) {
|
||||
GDTCORLogDebug(@"Registered metrics controller: %@ for target:%ld", metricsController,
|
||||
(long)target);
|
||||
strongSelf->_targetToMetricsController[@(target)] = metricsController;
|
||||
[self setMetricsControllerAsStorageDelegateForTarget:target];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
- (NSMutableDictionary<NSNumber *, id<GDTCORUploader>> *)targetToUploader {
|
||||
__block NSMutableDictionary<NSNumber *, id<GDTCORUploader>> *targetToUploader;
|
||||
__weak GDTCORRegistrar *weakSelf = self;
|
||||
dispatch_sync(_registrarQueue, ^{
|
||||
GDTCORRegistrar *strongSelf = weakSelf;
|
||||
if (strongSelf) {
|
||||
targetToUploader = strongSelf->_targetToUploader;
|
||||
}
|
||||
});
|
||||
return targetToUploader;
|
||||
}
|
||||
|
||||
- (NSMutableDictionary<NSNumber *, id<GDTCORStorageProtocol>> *)targetToStorage {
|
||||
__block NSMutableDictionary<NSNumber *, id<GDTCORStorageProtocol>> *targetToStorage;
|
||||
__weak GDTCORRegistrar *weakSelf = self;
|
||||
dispatch_sync(_registrarQueue, ^{
|
||||
GDTCORRegistrar *strongSelf = weakSelf;
|
||||
if (strongSelf) {
|
||||
targetToStorage = strongSelf->_targetToStorage;
|
||||
}
|
||||
});
|
||||
return targetToStorage;
|
||||
}
|
||||
|
||||
- (NSMutableDictionary<NSNumber *, id<GDTCORMetricsControllerProtocol>> *)
|
||||
targetToMetricsController {
|
||||
__block NSMutableDictionary<NSNumber *, id<GDTCORMetricsControllerProtocol>>
|
||||
*targetToMetricsController;
|
||||
__weak GDTCORRegistrar *weakSelf = self;
|
||||
dispatch_sync(_registrarQueue, ^{
|
||||
GDTCORRegistrar *strongSelf = weakSelf;
|
||||
if (strongSelf) {
|
||||
targetToMetricsController = strongSelf->_targetToMetricsController;
|
||||
}
|
||||
});
|
||||
return targetToMetricsController;
|
||||
}
|
||||
|
||||
- (void)setMetricsControllerAsStorageDelegateForTarget:(GDTCORTarget)target {
|
||||
_targetToStorage[@(target)].delegate = _targetToMetricsController[@(target)];
|
||||
}
|
||||
|
||||
#pragma mark - GDTCORLifecycleProtocol
|
||||
|
||||
- (void)appWillBackground:(nonnull GDTCORApplication *)app {
|
||||
NSArray<id<GDTCORUploader>> *uploaders = [self.targetToUploader allValues];
|
||||
for (id<GDTCORUploader> uploader in uploaders) {
|
||||
if ([uploader respondsToSelector:@selector(appWillBackground:)]) {
|
||||
[uploader appWillBackground:app];
|
||||
}
|
||||
}
|
||||
NSArray<id<GDTCORStorageProtocol>> *storages = [self.targetToStorage allValues];
|
||||
for (id<GDTCORStorageProtocol> storage in storages) {
|
||||
if ([storage respondsToSelector:@selector(appWillBackground:)]) {
|
||||
[storage appWillBackground:app];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)appWillForeground:(nonnull GDTCORApplication *)app {
|
||||
NSArray<id<GDTCORUploader>> *uploaders = [self.targetToUploader allValues];
|
||||
for (id<GDTCORUploader> uploader in uploaders) {
|
||||
if ([uploader respondsToSelector:@selector(appWillForeground:)]) {
|
||||
[uploader appWillForeground:app];
|
||||
}
|
||||
}
|
||||
NSArray<id<GDTCORStorageProtocol>> *storages = [self.targetToStorage allValues];
|
||||
for (id<GDTCORStorageProtocol> storage in storages) {
|
||||
if ([storage respondsToSelector:@selector(appWillForeground:)]) {
|
||||
[storage appWillForeground:app];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)appWillTerminate:(nonnull GDTCORApplication *)app {
|
||||
NSArray<id<GDTCORUploader>> *uploaders = [self.targetToUploader allValues];
|
||||
for (id<GDTCORUploader> uploader in uploaders) {
|
||||
if ([uploader respondsToSelector:@selector(appWillTerminate:)]) {
|
||||
[uploader appWillTerminate:app];
|
||||
}
|
||||
}
|
||||
NSArray<id<GDTCORStorageProtocol>> *storages = [self.targetToStorage allValues];
|
||||
for (id<GDTCORStorageProtocol> storage in storages) {
|
||||
if ([storage respondsToSelector:@selector(appWillTerminate:)]) {
|
||||
[storage appWillTerminate:app];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
39
Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORStorageEventSelector.m
generated
Normal file
39
Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORStorageEventSelector.m
generated
Normal file
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright 2020 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Internal/GDTCORStorageEventSelector.h"
|
||||
|
||||
@implementation GDTCORStorageEventSelector
|
||||
|
||||
+ (instancetype)eventSelectorForTarget:(GDTCORTarget)target {
|
||||
return [[self alloc] initWithTarget:target eventIDs:nil mappingIDs:nil qosTiers:nil];
|
||||
}
|
||||
|
||||
- (instancetype)initWithTarget:(GDTCORTarget)target
|
||||
eventIDs:(nullable NSSet<NSString *> *)eventIDs
|
||||
mappingIDs:(nullable NSSet<NSString *> *)mappingIDs
|
||||
qosTiers:(nullable NSSet<NSNumber *> *)qosTiers {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_selectedTarget = target;
|
||||
_selectedEventIDs = eventIDs;
|
||||
_selectedMappingIDs = mappingIDs;
|
||||
_selectedQosTiers = qosTiers;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
||||
36
Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORStorageMetadata.m
generated
Normal file
36
Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORStorageMetadata.m
generated
Normal file
@ -0,0 +1,36 @@
|
||||
// Copyright 2022 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Private/GDTCORStorageMetadata.h"
|
||||
|
||||
@implementation GDTCORStorageMetadata
|
||||
|
||||
- (instancetype)initWithCurrentCacheSize:(GDTCORStorageSizeBytes)currentCacheSize
|
||||
maxCacheSize:(GDTCORStorageSizeBytes)maxCacheSize {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_currentCacheSize = currentCacheSize;
|
||||
_maxCacheSize = maxCacheSize;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
+ (instancetype)metadataWithCurrentCacheSize:(GDTCORStorageSizeBytes)currentCacheSize
|
||||
maxCacheSize:(GDTCORStorageSizeBytes)maxCacheSize {
|
||||
return [[self alloc] initWithCurrentCacheSize:currentCacheSize maxCacheSize:maxCacheSize];
|
||||
}
|
||||
|
||||
@end
|
||||
108
Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORTransformer.m
generated
Normal file
108
Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORTransformer.m
generated
Normal file
@ -0,0 +1,108 @@
|
||||
/*
|
||||
* Copyright 2018 Google
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Private/GDTCORTransformer.h"
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Private/GDTCORTransformer_Private.h"
|
||||
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Internal/GDTCORAssert.h"
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Internal/GDTCORLifecycle.h"
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Internal/GDTCORStorageProtocol.h"
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORConsoleLogger.h"
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCOREvent.h"
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCOREventTransformer.h"
|
||||
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Private/GDTCOREvent_Private.h"
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Private/GDTCORRegistrar_Private.h"
|
||||
|
||||
@implementation GDTCORTransformer
|
||||
|
||||
+ (instancetype)sharedInstance {
|
||||
static GDTCORTransformer *eventTransformer;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
eventTransformer = [[self alloc] init];
|
||||
});
|
||||
return eventTransformer;
|
||||
}
|
||||
|
||||
- (instancetype)init {
|
||||
return [self initWithApplication:[GDTCORApplication sharedApplication]];
|
||||
}
|
||||
|
||||
- (instancetype)initWithApplication:(id<GDTCORApplicationProtocol>)application {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_eventWritingQueue =
|
||||
dispatch_queue_create("com.google.GDTCORTransformer", DISPATCH_QUEUE_SERIAL);
|
||||
_application = application;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)transformEvent:(GDTCOREvent *)event
|
||||
withTransformers:(NSArray<id<GDTCOREventTransformer>> *)transformers
|
||||
onComplete:(void (^_Nullable)(BOOL wasWritten, NSError *_Nullable error))completion {
|
||||
GDTCORAssert(event, @"You can't write a nil event");
|
||||
|
||||
__block GDTCORBackgroundIdentifier bgID = GDTCORBackgroundIdentifierInvalid;
|
||||
__auto_type __weak weakApplication = self.application;
|
||||
bgID = [self.application beginBackgroundTaskWithName:@"GDTTransformer"
|
||||
expirationHandler:^{
|
||||
[weakApplication endBackgroundTask:bgID];
|
||||
bgID = GDTCORBackgroundIdentifierInvalid;
|
||||
}];
|
||||
|
||||
__auto_type completionWrapper = ^(BOOL wasWritten, NSError *_Nullable error) {
|
||||
if (completion) {
|
||||
completion(wasWritten, error);
|
||||
}
|
||||
|
||||
if (bgID != GDTCORBackgroundIdentifierInvalid) {
|
||||
// The work is done, cancel the background task if it's valid.
|
||||
[weakApplication endBackgroundTask:bgID];
|
||||
} else {
|
||||
GDTCORLog(GDTCORMCDDebugLog, GDTCORLoggingLevelWarnings,
|
||||
@"Attempted to cancel invalid background task in GDTCORTransformer.");
|
||||
}
|
||||
bgID = GDTCORBackgroundIdentifierInvalid;
|
||||
};
|
||||
|
||||
dispatch_async(_eventWritingQueue, ^{
|
||||
GDTCOREvent *transformedEvent = event;
|
||||
for (id<GDTCOREventTransformer> transformer in transformers) {
|
||||
if ([transformer respondsToSelector:@selector(transformGDTEvent:)]) {
|
||||
GDTCORLogDebug(@"Applying a transformer to event %@", event);
|
||||
transformedEvent = [transformer transformGDTEvent:event];
|
||||
if (!transformedEvent) {
|
||||
completionWrapper(NO, nil);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
GDTCORLogError(GDTCORMCETransformerDoesntImplementTransform,
|
||||
@"Transformer doesn't implement transformGDTEvent: %@", transformer);
|
||||
completionWrapper(NO, nil);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
id<GDTCORStorageProtocol> storage =
|
||||
[GDTCORRegistrar sharedInstance].targetToStorage[@(event.target)];
|
||||
|
||||
[storage storeEvent:transformedEvent onComplete:completionWrapper];
|
||||
});
|
||||
}
|
||||
|
||||
@end
|
||||
108
Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORTransport.m
generated
Normal file
108
Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORTransport.m
generated
Normal file
@ -0,0 +1,108 @@
|
||||
/*
|
||||
* Copyright 2018 Google
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORTransport.h"
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Private/GDTCORTransport_Private.h"
|
||||
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Internal/GDTCORAssert.h"
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORClock.h"
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCOREvent.h"
|
||||
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Private/GDTCORTransformer.h"
|
||||
|
||||
@implementation GDTCORTransport
|
||||
|
||||
- (nullable instancetype)initWithMappingID:(NSString *)mappingID
|
||||
transformers:
|
||||
(nullable NSArray<id<GDTCOREventTransformer>> *)transformers
|
||||
target:(GDTCORTarget)target {
|
||||
GDTCORAssert(mappingID.length > 0, @"A mapping ID cannot be nil or empty");
|
||||
GDTCORAssert(target > 0, @"A target cannot be negative or 0");
|
||||
if (mappingID == nil || mappingID.length == 0 || target <= 0) {
|
||||
return nil;
|
||||
}
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_mappingID = mappingID;
|
||||
_transformers = transformers;
|
||||
_target = target;
|
||||
_transformerInstance = [GDTCORTransformer sharedInstance];
|
||||
}
|
||||
GDTCORLogDebug(@"Transport object created. mappingID:%@ transformers:%@ target:%ld", mappingID,
|
||||
transformers, (long)target);
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)sendTelemetryEvent:(GDTCOREvent *)event
|
||||
onComplete:
|
||||
(void (^_Nullable)(BOOL wasWritten, NSError *_Nullable error))completion {
|
||||
event.qosTier = GDTCOREventQoSTelemetry;
|
||||
[self sendEvent:event onComplete:completion];
|
||||
}
|
||||
|
||||
- (void)sendDataEvent:(GDTCOREvent *)event
|
||||
onComplete:(void (^_Nullable)(BOOL wasWritten, NSError *_Nullable error))completion {
|
||||
GDTCORAssert(event.qosTier != GDTCOREventQoSTelemetry, @"Use -sendTelemetryEvent, please.");
|
||||
[self sendEvent:event onComplete:completion];
|
||||
}
|
||||
|
||||
- (void)sendTelemetryEvent:(GDTCOREvent *)event {
|
||||
[self sendTelemetryEvent:event onComplete:nil];
|
||||
}
|
||||
|
||||
- (void)sendDataEvent:(GDTCOREvent *)event {
|
||||
[self sendDataEvent:event onComplete:nil];
|
||||
}
|
||||
|
||||
- (GDTCOREvent *)eventForTransport {
|
||||
return [[GDTCOREvent alloc] initWithMappingID:_mappingID target:_target];
|
||||
}
|
||||
|
||||
- (GDTCOREvent *)eventForTransportWithProductData:(GDTCORProductData *)productData {
|
||||
return [[GDTCOREvent alloc] initWithMappingID:_mappingID productData:productData target:_target];
|
||||
}
|
||||
|
||||
#pragma mark - Private helper methods
|
||||
|
||||
/** Sends the given event through the transport pipeline.
|
||||
*
|
||||
* @param event The event to send.
|
||||
* @param completion A block that will be called when the event has been written or dropped.
|
||||
*/
|
||||
- (void)sendEvent:(GDTCOREvent *)event
|
||||
onComplete:(void (^_Nullable)(BOOL wasWritten, NSError *_Nullable error))completion {
|
||||
// TODO: Determine if sending an event before registration is allowed.
|
||||
GDTCORAssert(event, @"You can't send a nil event");
|
||||
GDTCOREvent *copiedEvent = [event copy];
|
||||
copiedEvent.clockSnapshot = [GDTCORClock snapshot];
|
||||
[self.transformerInstance transformEvent:copiedEvent
|
||||
withTransformers:_transformers
|
||||
onComplete:completion];
|
||||
}
|
||||
|
||||
#pragma mark - Force Category Linking
|
||||
|
||||
extern void GDTCORInclude_GDTCORLogSourceMetrics_Internal_Category(void);
|
||||
|
||||
/// Does nothing when called, and not meant to be called.
|
||||
///
|
||||
/// This method forces the linker to include categories even if
|
||||
/// users do not include the '-ObjC' linker flag in their project.
|
||||
+ (void)noop {
|
||||
GDTCORInclude_GDTCORLogSourceMetrics_Internal_Category();
|
||||
}
|
||||
|
||||
@end
|
||||
30
Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORUploadBatch.m
generated
Normal file
30
Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORUploadBatch.m
generated
Normal file
@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright 2020 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Private/GDTCORUploadBatch.h"
|
||||
|
||||
@implementation GDTCORUploadBatch
|
||||
|
||||
- (instancetype)initWithBatchID:(NSNumber *)batchID events:(NSSet<GDTCOREvent *> *)events {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_batchID = batchID;
|
||||
_events = events;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
||||
176
Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORUploadCoordinator.m
generated
Normal file
176
Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORUploadCoordinator.m
generated
Normal file
@ -0,0 +1,176 @@
|
||||
/*
|
||||
* Copyright 2018 Google
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Private/GDTCORUploadCoordinator.h"
|
||||
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Internal/GDTCORAssert.h"
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Internal/GDTCORReachability.h"
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORClock.h"
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORConsoleLogger.h"
|
||||
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Private/GDTCORRegistrar_Private.h"
|
||||
|
||||
@implementation GDTCORUploadCoordinator
|
||||
|
||||
+ (instancetype)sharedInstance {
|
||||
static GDTCORUploadCoordinator *sharedUploader;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
sharedUploader = [[GDTCORUploadCoordinator alloc] init];
|
||||
[sharedUploader startTimer];
|
||||
});
|
||||
return sharedUploader;
|
||||
}
|
||||
|
||||
- (instancetype)init {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_coordinationQueue =
|
||||
dispatch_queue_create("com.google.GDTCORUploadCoordinator", DISPATCH_QUEUE_SERIAL);
|
||||
_registrar = [GDTCORRegistrar sharedInstance];
|
||||
_timerInterval = 30 * NSEC_PER_SEC;
|
||||
_timerLeeway = 5 * NSEC_PER_SEC;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)forceUploadForTarget:(GDTCORTarget)target {
|
||||
dispatch_async(_coordinationQueue, ^{
|
||||
GDTCORLogDebug(@"Forcing an upload of target %ld", (long)target);
|
||||
GDTCORUploadConditions conditions = [self uploadConditions];
|
||||
conditions |= GDTCORUploadConditionHighPriority;
|
||||
[self uploadTargets:@[ @(target) ] conditions:conditions];
|
||||
});
|
||||
}
|
||||
|
||||
#pragma mark - Private helper methods
|
||||
|
||||
/** Starts a timer that checks whether or not events can be uploaded at regular intervals. It will
|
||||
* check the next-upload clocks of all targets to determine if an upload attempt can be made.
|
||||
*/
|
||||
- (void)startTimer {
|
||||
dispatch_async(_coordinationQueue, ^{
|
||||
if (self->_timer) {
|
||||
// The timer has been already started.
|
||||
return;
|
||||
}
|
||||
|
||||
// Delay the timer slightly so it doesn't run while +load calls are still running.
|
||||
dispatch_time_t deadline = dispatch_time(DISPATCH_TIME_NOW, 1 * NSEC_PER_SEC / 2);
|
||||
|
||||
self->_timer =
|
||||
dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, self->_coordinationQueue);
|
||||
dispatch_source_set_timer(self->_timer, deadline, self->_timerInterval, self->_timerLeeway);
|
||||
|
||||
dispatch_source_set_event_handler(self->_timer, ^{
|
||||
if (![[GDTCORApplication sharedApplication] isRunningInBackground]) {
|
||||
GDTCORUploadConditions conditions = [self uploadConditions];
|
||||
GDTCORLogDebug(@"%@", @"Upload timer fired");
|
||||
[self uploadTargets:[self.registrar.targetToUploader allKeys] conditions:conditions];
|
||||
}
|
||||
});
|
||||
GDTCORLogDebug(@"%@", @"Upload timer started");
|
||||
dispatch_resume(self->_timer);
|
||||
});
|
||||
}
|
||||
|
||||
/** Stops the currently running timer. */
|
||||
- (void)stopTimer {
|
||||
if (_timer) {
|
||||
dispatch_source_cancel(_timer);
|
||||
_timer = nil;
|
||||
}
|
||||
}
|
||||
|
||||
/** Triggers the uploader implementations for the given targets to upload.
|
||||
*
|
||||
* @param targets An array of targets to trigger.
|
||||
* @param conditions The set of upload conditions.
|
||||
*/
|
||||
- (void)uploadTargets:(NSArray<NSNumber *> *)targets conditions:(GDTCORUploadConditions)conditions {
|
||||
dispatch_async(_coordinationQueue, ^{
|
||||
// TODO: The reachability signal may be not reliable enough to prevent an upload attempt.
|
||||
// See https://developer.apple.com/videos/play/wwdc2019/712/ (49:40) for more details.
|
||||
if ((conditions & GDTCORUploadConditionNoNetwork) == GDTCORUploadConditionNoNetwork) {
|
||||
return;
|
||||
}
|
||||
for (NSNumber *target in targets) {
|
||||
id<GDTCORUploader> uploader = self->_registrar.targetToUploader[target];
|
||||
[uploader uploadTarget:target.intValue withConditions:conditions];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
- (void)signalToStoragesToCheckExpirations {
|
||||
// The same storage may be associated with several targets. Make sure to check for expirations
|
||||
// only once per storage.
|
||||
NSSet<id<GDTCORStorageProtocol>> *storages =
|
||||
[NSSet setWithArray:[_registrar.targetToStorage allValues]];
|
||||
for (id<GDTCORStorageProtocol> storage in storages) {
|
||||
[storage checkForExpirations];
|
||||
}
|
||||
}
|
||||
|
||||
/** Returns the registered storage for the given NSNumber wrapped GDTCORTarget.
|
||||
*
|
||||
* @param target The NSNumber wrapping of a GDTCORTarget to find the storage instance of.
|
||||
* @return The storage instance for the given target.
|
||||
*/
|
||||
- (nullable id<GDTCORStorageProtocol>)storageForTarget:(NSNumber *)target {
|
||||
id<GDTCORStorageProtocol> storage = [GDTCORRegistrar sharedInstance].targetToStorage[target];
|
||||
GDTCORAssert(storage, @"A storage must be registered for target %@", target);
|
||||
return storage;
|
||||
}
|
||||
|
||||
/** Returns the current upload conditions after making determinations about the network connection.
|
||||
*
|
||||
* @return The current upload conditions.
|
||||
*/
|
||||
- (GDTCORUploadConditions)uploadConditions {
|
||||
GDTCORNetworkReachabilityFlags currentFlags = [GDTCORReachability currentFlags];
|
||||
BOOL networkConnected = GDTCORReachabilityFlagsReachable(currentFlags);
|
||||
if (!networkConnected) {
|
||||
return GDTCORUploadConditionNoNetwork;
|
||||
}
|
||||
BOOL isWWAN = GDTCORReachabilityFlagsContainWWAN(currentFlags);
|
||||
if (isWWAN) {
|
||||
return GDTCORUploadConditionMobileData;
|
||||
} else {
|
||||
return GDTCORUploadConditionWifiData;
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - GDTCORLifecycleProtocol
|
||||
|
||||
- (void)appWillForeground:(GDTCORApplication *)app {
|
||||
// -startTimer is thread-safe.
|
||||
[self startTimer];
|
||||
[self signalToStoragesToCheckExpirations];
|
||||
}
|
||||
|
||||
- (void)appWillBackground:(GDTCORApplication *)app {
|
||||
dispatch_async(_coordinationQueue, ^{
|
||||
[self stopTimer];
|
||||
});
|
||||
}
|
||||
|
||||
- (void)appWillTerminate:(GDTCORApplication *)application {
|
||||
dispatch_async(_coordinationQueue, ^{
|
||||
[self stopTimer];
|
||||
});
|
||||
}
|
||||
|
||||
@end
|
||||
95
Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Internal/GDTCORAssert.h
generated
Normal file
95
Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Internal/GDTCORAssert.h
generated
Normal file
@ -0,0 +1,95 @@
|
||||
/*
|
||||
* Copyright 2019 Google
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORConsoleLogger.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/** A block type that could be run instead of normal assertion logging. No return type, no params.
|
||||
*/
|
||||
typedef void (^GDTCORAssertionBlock)(void);
|
||||
|
||||
/** Returns the result of executing a soft-linked method present in unit tests that allows a block
|
||||
* to be run instead of normal assertion logging. This helps ameliorate issues with catching
|
||||
* exceptions that occur on a dispatch_queue.
|
||||
*
|
||||
* @return A block that can be run instead of normal assert printing.
|
||||
*/
|
||||
FOUNDATION_EXPORT GDTCORAssertionBlock _Nullable GDTCORAssertionBlockToRunInstead(void);
|
||||
|
||||
#if defined(NS_BLOCK_ASSERTIONS)
|
||||
|
||||
#define GDTCORAssert(condition, ...) \
|
||||
do { \
|
||||
} while (0);
|
||||
|
||||
#define GDTCORFatalAssert(condition, ...) \
|
||||
do { \
|
||||
} while (0);
|
||||
|
||||
#else // defined(NS_BLOCK_ASSERTIONS)
|
||||
|
||||
/** Asserts using a console log, unless a block was specified to be run instead.
|
||||
*
|
||||
* @param condition The condition you'd expect to be YES.
|
||||
*/
|
||||
#define GDTCORAssert(condition, format, ...) \
|
||||
do { \
|
||||
__PRAGMA_PUSH_NO_EXTRA_ARG_WARNINGS \
|
||||
if (__builtin_expect(!(condition), 0)) { \
|
||||
GDTCORAssertionBlock assertionBlock = GDTCORAssertionBlockToRunInstead(); \
|
||||
if (assertionBlock) { \
|
||||
assertionBlock(); \
|
||||
} else { \
|
||||
NSString *__assert_file__ = [NSString stringWithUTF8String:__FILE__]; \
|
||||
__assert_file__ = __assert_file__ ? __assert_file__ : @"<Unknown File>"; \
|
||||
GDTCORLogAssert(NO, __assert_file__, __LINE__, format, ##__VA_ARGS__); \
|
||||
__PRAGMA_POP_NO_EXTRA_ARG_WARNINGS \
|
||||
} \
|
||||
} \
|
||||
} while (0);
|
||||
|
||||
/** Asserts by logging to the console and throwing an exception if NS_BLOCK_ASSERTIONS is not
|
||||
* defined.
|
||||
*
|
||||
* @param condition The condition you'd expect to be YES.
|
||||
*/
|
||||
#define GDTCORFatalAssert(condition, format, ...) \
|
||||
do { \
|
||||
__PRAGMA_PUSH_NO_EXTRA_ARG_WARNINGS \
|
||||
if (__builtin_expect(!(condition), 0)) { \
|
||||
GDTCORAssertionBlock assertionBlock = GDTCORAssertionBlockToRunInstead(); \
|
||||
if (assertionBlock) { \
|
||||
assertionBlock(); \
|
||||
} else { \
|
||||
NSString *__assert_file__ = [NSString stringWithUTF8String:__FILE__]; \
|
||||
__assert_file__ = __assert_file__ ? __assert_file__ : @"<Unknown File>"; \
|
||||
GDTCORLogAssert(YES, __assert_file__, __LINE__, format, ##__VA_ARGS__); \
|
||||
[[NSAssertionHandler currentHandler] handleFailureInMethod:_cmd \
|
||||
object:self \
|
||||
file:__assert_file__ \
|
||||
lineNumber:__LINE__ \
|
||||
description:format, ##__VA_ARGS__]; \
|
||||
__PRAGMA_POP_NO_EXTRA_ARG_WARNINGS \
|
||||
} \
|
||||
} \
|
||||
} while (0);
|
||||
|
||||
#endif // defined(NS_BLOCK_ASSERTIONS)
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
66
Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Internal/GDTCORDirectorySizeTracker.h
generated
Normal file
66
Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Internal/GDTCORDirectorySizeTracker.h
generated
Normal file
@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright 2020 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Internal/GDTCORStorageProtocol.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/** The class calculates and caches the specified directory content size and uses add/remove signals
|
||||
* from client the client to keep the size up to date without accessing file system.
|
||||
* This is an internal class designed to be used by `GDTCORFlatFileStorage`.
|
||||
* NOTE: The class is not thread-safe. The client must take care of synchronization.
|
||||
*/
|
||||
@interface GDTCORDirectorySizeTracker : NSObject
|
||||
|
||||
- (instancetype)init NS_UNAVAILABLE;
|
||||
|
||||
/** Initializes the object with a directory path.
|
||||
* @param path The directory path to track content size.
|
||||
*/
|
||||
- (instancetype)initWithDirectoryPath:(NSString *)path;
|
||||
|
||||
/** Returns a cached or calculates (if there is no cached) directory content size.
|
||||
* @return The directory content size in bytes calculated based on `NSURLFileSizeKey`.
|
||||
*/
|
||||
- (GDTCORStorageSizeBytes)directoryContentSize;
|
||||
|
||||
/** The client must call this method or `resetCachedSize` method each time a file or directory is
|
||||
* added to the tracked directory.
|
||||
* @param path The path to the added file. If the path is outside the tracked directory then the
|
||||
* @param fileSize The size of the added file.
|
||||
* method is no-op.
|
||||
*/
|
||||
- (void)fileWasAddedAtPath:(NSString *)path withSize:(GDTCORStorageSizeBytes)fileSize;
|
||||
|
||||
/** The client must call this method or `resetCachedSize` method each time a file or directory is
|
||||
* removed from the tracked directory.
|
||||
* @param path The path to the removed file. If the path is outside the tracked directory then the
|
||||
* @param fileSize The size of the removed file.
|
||||
* method is no-op.
|
||||
*/
|
||||
- (void)fileWasRemovedAtPath:(NSString *)path withSize:(GDTCORStorageSizeBytes)fileSize;
|
||||
|
||||
/** Invalidates cached directory size. */
|
||||
- (void)resetCachedSize;
|
||||
|
||||
/** Returns URL resource value for `NSURLFileSizeKey` key for the specified URL. */
|
||||
- (GDTCORStorageSizeBytes)fileSizeAtURL:(NSURL *)fileURL;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
27
Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Internal/GDTCOREventDropReason.h
generated
Normal file
27
Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Internal/GDTCOREventDropReason.h
generated
Normal file
@ -0,0 +1,27 @@
|
||||
// Copyright 2022 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
/// The reason the event was "dropped". An event is considered "dropped" when it is no longer
|
||||
/// tracked by the SDK (i.e. deleted).
|
||||
typedef NS_ENUM(NSInteger, GDTCOREventDropReason) {
|
||||
GDTCOREventDropReasonUnknown = 0,
|
||||
GDTCOREventDropReasonMessageTooOld,
|
||||
GDTCOREventDropReasonStorageFull,
|
||||
GDTCOREventDropReasonPayloadTooBig,
|
||||
GDTCOREventDropReasonMaxRetriesReached,
|
||||
GDTCOREventDropReasonInvalidPayload,
|
||||
GDTCOREventDropReasonServerError
|
||||
};
|
||||
63
Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Internal/GDTCORLifecycle.h
generated
Normal file
63
Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Internal/GDTCORLifecycle.h
generated
Normal file
@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright 2019 Google
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Internal/GDTCORPlatform.h"
|
||||
|
||||
@class GDTCOREvent;
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/** A protocol defining the lifecycle events objects in the library must respond to immediately. */
|
||||
@protocol GDTCORLifecycleProtocol <NSObject>
|
||||
|
||||
@optional
|
||||
|
||||
/** Indicates an imminent app termination in the rare occurrence when -applicationWillTerminate: has
|
||||
* been called.
|
||||
*
|
||||
* @param app The GDTCORApplication instance.
|
||||
*/
|
||||
- (void)appWillTerminate:(GDTCORApplication *)app;
|
||||
|
||||
/** Indicates that the app is moving to background and eventual suspension or the current UIScene is
|
||||
* deactivating.
|
||||
*
|
||||
* @param app The GDTCORApplication instance.
|
||||
*/
|
||||
- (void)appWillBackground:(GDTCORApplication *)app;
|
||||
|
||||
/** Indicates that the app is resuming operation or a UIScene is activating.
|
||||
*
|
||||
* @param app The GDTCORApplication instance.
|
||||
*/
|
||||
- (void)appWillForeground:(GDTCORApplication *)app;
|
||||
|
||||
@end
|
||||
|
||||
/** This class manages the library's response to app lifecycle events.
|
||||
*
|
||||
* When backgrounding, the library doesn't stop processing events, it's just that several background
|
||||
* tasks will end up being created for every event that's sent, and the stateful objects of the
|
||||
* library (GDTCORStorage and GDTCORUploadCoordinator instances) will deserialize themselves from
|
||||
* and to disk before and after every operation, respectively.
|
||||
*/
|
||||
@interface GDTCORLifecycle : NSObject
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright 2022 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Internal/GDTCOREventDropReason.h"
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Internal/GDTCORStorageProtocol.h"
|
||||
|
||||
@class FBLPromise<ResultType>;
|
||||
@class GDTCOREvent;
|
||||
@class GDTCORMetrics;
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/// A storage delegate that can perform metrics related tasks.
|
||||
@protocol GDTCORMetricsControllerProtocol <GDTCORStorageDelegate>
|
||||
|
||||
/// Updates the corresponding log source metricss for the given events dropped for a given
|
||||
/// reason.
|
||||
/// @param reason The reason why the events are being dropped.
|
||||
/// @param events The events that being dropped.
|
||||
- (FBLPromise<NSNull *> *)logEventsDroppedForReason:(GDTCOREventDropReason)reason
|
||||
events:(NSSet<GDTCOREvent *> *)events;
|
||||
|
||||
/// Gets and resets the currently stored metrics.
|
||||
/// @return A promise resolving with the metrics retrieved before the reset.
|
||||
- (FBLPromise<GDTCORMetrics *> *)getAndResetMetrics;
|
||||
|
||||
/// Offers metrics for re-storing in storage.
|
||||
/// @note If the metrics are determined to be from the future, they will be ignored.
|
||||
/// @param metrics The metrics to offer for storage.
|
||||
- (FBLPromise<NSNull *> *)offerMetrics:(GDTCORMetrics *)metrics;
|
||||
|
||||
@end
|
||||
|
||||
/// Returns a metrics controller instance for the given target.
|
||||
/// @param target The target to retrieve a corresponding metrics controller from.
|
||||
/// @return The given target's corresponding metrics controller instance, or `nil` if it does not
|
||||
/// have one.
|
||||
FOUNDATION_EXPORT
|
||||
id<GDTCORMetricsControllerProtocol> _Nullable GDTCORMetricsControllerInstanceForTarget(
|
||||
GDTCORTarget target);
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
232
Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Internal/GDTCORPlatform.h
generated
Normal file
232
Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Internal/GDTCORPlatform.h
generated
Normal file
@ -0,0 +1,232 @@
|
||||
/*
|
||||
* Copyright 2019 Google
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#if !TARGET_OS_WATCH
|
||||
#import <SystemConfiguration/SystemConfiguration.h>
|
||||
#endif
|
||||
|
||||
#if TARGET_OS_IOS || TARGET_OS_TV
|
||||
#import <UIKit/UIKit.h>
|
||||
#elif TARGET_OS_OSX
|
||||
#import <AppKit/AppKit.h>
|
||||
#elif TARGET_OS_WATCH
|
||||
#import <WatchKit/WatchKit.h>
|
||||
#endif // TARGET_OS_IOS || TARGET_OS_TV
|
||||
|
||||
// TODO(Xcode 15): When Xcode 15 is the minimum supported Xcode version,
|
||||
// it will be unnecessary to check if `TARGET_OS_VISION` is defined.
|
||||
#if TARGET_OS_IOS && (!defined(TARGET_OS_VISION) || !TARGET_OS_VISION)
|
||||
#import <CoreTelephony/CTTelephonyNetworkInfo.h>
|
||||
#endif
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/** The GoogleDataTransport library version. */
|
||||
FOUNDATION_EXPORT NSString *const kGDTCORVersion;
|
||||
|
||||
/** A notification sent out if the app is backgrounding. */
|
||||
FOUNDATION_EXPORT NSString *const kGDTCORApplicationDidEnterBackgroundNotification;
|
||||
|
||||
/** A notification sent out if the app is foregrounding. */
|
||||
FOUNDATION_EXPORT NSString *const kGDTCORApplicationWillEnterForegroundNotification;
|
||||
|
||||
/** A notification sent out if the app is terminating. */
|
||||
FOUNDATION_EXPORT NSString *const kGDTCORApplicationWillTerminateNotification;
|
||||
|
||||
/** The different possible network connection type. */
|
||||
typedef NS_ENUM(NSInteger, GDTCORNetworkType) {
|
||||
GDTCORNetworkTypeUNKNOWN = 0,
|
||||
GDTCORNetworkTypeWIFI = 1,
|
||||
GDTCORNetworkTypeMobile = 2,
|
||||
};
|
||||
|
||||
/** The different possible network connection mobile subtype. */
|
||||
typedef NS_ENUM(NSInteger, GDTCORNetworkMobileSubtype) {
|
||||
GDTCORNetworkMobileSubtypeUNKNOWN = 0,
|
||||
GDTCORNetworkMobileSubtypeGPRS = 1,
|
||||
GDTCORNetworkMobileSubtypeEdge = 2,
|
||||
GDTCORNetworkMobileSubtypeWCDMA = 3,
|
||||
GDTCORNetworkMobileSubtypeHSDPA = 4,
|
||||
GDTCORNetworkMobileSubtypeHSUPA = 5,
|
||||
GDTCORNetworkMobileSubtypeCDMA1x = 6,
|
||||
GDTCORNetworkMobileSubtypeCDMAEVDORev0 = 7,
|
||||
GDTCORNetworkMobileSubtypeCDMAEVDORevA = 8,
|
||||
GDTCORNetworkMobileSubtypeCDMAEVDORevB = 9,
|
||||
GDTCORNetworkMobileSubtypeHRPD = 10,
|
||||
GDTCORNetworkMobileSubtypeLTE = 11,
|
||||
};
|
||||
|
||||
#if !TARGET_OS_WATCH
|
||||
/** Define SCNetworkReachabilityFlags as GDTCORNetworkReachabilityFlags on non-watchOS. */
|
||||
typedef SCNetworkReachabilityFlags GDTCORNetworkReachabilityFlags;
|
||||
|
||||
/** Define SCNetworkReachabilityRef as GDTCORNetworkReachabilityRef on non-watchOS. */
|
||||
typedef SCNetworkReachabilityRef GDTCORNetworkReachabilityRef;
|
||||
|
||||
#else
|
||||
/** The different possible reachabilityFlags option on watchOS. */
|
||||
typedef NS_OPTIONS(uint32_t, GDTCORNetworkReachabilityFlags) {
|
||||
kGDTCORNetworkReachabilityFlagsReachable = 1 << 1,
|
||||
// TODO(doudounan): Add more options on watchOS if watchOS network connection information relative
|
||||
// APIs available in the future.
|
||||
};
|
||||
|
||||
/** Define a struct as GDTCORNetworkReachabilityRef on watchOS to store network connection
|
||||
* information. */
|
||||
typedef struct {
|
||||
// TODO(doudounan): Store network connection information on watchOS if watchOS network connection
|
||||
// information relative APIs available in the future.
|
||||
} GDTCORNetworkReachabilityRef;
|
||||
#endif
|
||||
|
||||
/** Returns a URL to the root directory under which all GDT-associated data must be saved.
|
||||
*
|
||||
* @return A URL to the root directory under which all GDT-associated data must be saved.
|
||||
*/
|
||||
NSURL *GDTCORRootDirectory(void);
|
||||
|
||||
/** Compares flags with the reachable flag (on non-watchos with both reachable and
|
||||
* connectionRequired flags), if available, and returns YES if network reachable.
|
||||
*
|
||||
* @param flags The set of reachability flags.
|
||||
* @return YES if the network is reachable, NO otherwise.
|
||||
*/
|
||||
BOOL GDTCORReachabilityFlagsReachable(GDTCORNetworkReachabilityFlags flags);
|
||||
|
||||
/** Compares flags with the WWAN reachability flag, if available, and returns YES if present.
|
||||
*
|
||||
* @param flags The set of reachability flags.
|
||||
* @return YES if the WWAN flag is set, NO otherwise.
|
||||
*/
|
||||
BOOL GDTCORReachabilityFlagsContainWWAN(GDTCORNetworkReachabilityFlags flags);
|
||||
|
||||
/** Generates an enum message GDTCORNetworkType representing network connection type.
|
||||
*
|
||||
* @return A GDTCORNetworkType representing network connection type.
|
||||
*/
|
||||
GDTCORNetworkType GDTCORNetworkTypeMessage(void);
|
||||
|
||||
/** Generates an enum message GDTCORNetworkMobileSubtype representing network connection mobile
|
||||
* subtype.
|
||||
*
|
||||
* @return A GDTCORNetworkMobileSubtype representing network connection mobile subtype.
|
||||
*/
|
||||
GDTCORNetworkMobileSubtype GDTCORNetworkMobileSubTypeMessage(void);
|
||||
|
||||
/** Identifies the model of the device on which the library is currently working on.
|
||||
*
|
||||
* @return A NSString representing the device model.
|
||||
*/
|
||||
NSString *_Nonnull GDTCORDeviceModel(void);
|
||||
|
||||
/** Writes the given object to the given fileURL and populates the given error if it fails.
|
||||
*
|
||||
* @param obj The object to encode.
|
||||
* @param filePath The path to write the object to. Can be nil if you just need the data.
|
||||
* @param error The error to populate if something goes wrong.
|
||||
* @return The data of the archive. If error is nil, it's been written to disk.
|
||||
*/
|
||||
NSData *_Nullable GDTCOREncodeArchive(id<NSSecureCoding> obj,
|
||||
NSString *_Nullable filePath,
|
||||
NSError *_Nullable *error);
|
||||
|
||||
/// Decodes an object of the given class from the given archive path and populates the given error
|
||||
/// if it fails.
|
||||
/// @param archiveClass The class of the archive's root object.
|
||||
/// @param archivePath The path to the archived data.
|
||||
/// @param error The error to populate if something goes wrong.
|
||||
id<NSSecureCoding> _Nullable GDTCORDecodeArchiveAtPath(Class archiveClass,
|
||||
NSString *_Nonnull archivePath,
|
||||
NSError **_Nonnull error);
|
||||
|
||||
/// Decodes an object of the given class from the given data and populates the given error if it
|
||||
/// fails.
|
||||
/// @param archiveClass The class of the archive's root object.
|
||||
/// @param archiveData The data to decode.
|
||||
/// @param error The error to populate if something goes wrong.
|
||||
id<NSSecureCoding> _Nullable GDTCORDecodeArchive(Class archiveClass,
|
||||
NSData *_Nonnull archiveData,
|
||||
NSError **_Nonnull error);
|
||||
|
||||
/** Writes the provided data to a file at the provided path. Intermediate directories will be
|
||||
* created as needed.
|
||||
* @param data The file content.
|
||||
* @param filePath The path to the file to write the provided data.
|
||||
* @param outError The error to populate if something goes wrong.
|
||||
* @return `YES` in the case of success, `NO` otherwise.
|
||||
*/
|
||||
BOOL GDTCORWriteDataToFile(NSData *data, NSString *filePath, NSError *_Nullable *outError);
|
||||
|
||||
/** A typedef identify background identifiers. */
|
||||
typedef volatile NSUInteger GDTCORBackgroundIdentifier;
|
||||
|
||||
/** A background task's invalid sentinel value. */
|
||||
FOUNDATION_EXPORT const GDTCORBackgroundIdentifier GDTCORBackgroundIdentifierInvalid;
|
||||
|
||||
#if TARGET_OS_IOS || TARGET_OS_TV
|
||||
/** A protocol that wraps UIApplicationDelegate, WKExtensionDelegate or NSObject protocol, depending
|
||||
* on the platform.
|
||||
*/
|
||||
@protocol GDTCORApplicationDelegate <UIApplicationDelegate>
|
||||
#elif TARGET_OS_OSX
|
||||
@protocol GDTCORApplicationDelegate <NSApplicationDelegate>
|
||||
#elif TARGET_OS_WATCH
|
||||
@protocol GDTCORApplicationDelegate <WKExtensionDelegate>
|
||||
#else
|
||||
@protocol GDTCORApplicationDelegate <NSObject>
|
||||
#endif // TARGET_OS_IOS || TARGET_OS_TV
|
||||
|
||||
@end
|
||||
|
||||
@protocol GDTCORApplicationProtocol <NSObject>
|
||||
|
||||
@required
|
||||
|
||||
/** Flag to determine if the application is running in the background. */
|
||||
@property(atomic, readonly) BOOL isRunningInBackground;
|
||||
|
||||
/** Creates a background task with the returned identifier if on a suitable platform.
|
||||
*
|
||||
* @name name The name of the task, useful for debugging which background tasks are running.
|
||||
* @param handler The handler block that is called if the background task expires.
|
||||
* @return An identifier for the background task, or GDTCORBackgroundIdentifierInvalid if one
|
||||
* couldn't be created.
|
||||
*/
|
||||
- (GDTCORBackgroundIdentifier)beginBackgroundTaskWithName:(NSString *)name
|
||||
expirationHandler:(void (^__nullable)(void))handler;
|
||||
|
||||
/** Ends the background task if the identifier is valid.
|
||||
*
|
||||
* @param bgID The background task to end.
|
||||
*/
|
||||
- (void)endBackgroundTask:(GDTCORBackgroundIdentifier)bgID;
|
||||
|
||||
@end
|
||||
|
||||
/** A cross-platform application class. */
|
||||
@interface GDTCORApplication : NSObject <GDTCORApplicationProtocol, GDTCORApplicationDelegate>
|
||||
|
||||
/** Creates and/or returns the shared application instance.
|
||||
*
|
||||
* @return The shared application instance.
|
||||
*/
|
||||
+ (nullable GDTCORApplication *)sharedApplication;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
31
Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Internal/GDTCORReachability.h
generated
Normal file
31
Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Internal/GDTCORReachability.h
generated
Normal file
@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright 2019 Google
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Internal/GDTCORPlatform.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/** This class helps determine upload conditions by determining connectivity. */
|
||||
@interface GDTCORReachability : NSObject
|
||||
|
||||
/** The current set flags indicating network conditions */
|
||||
+ (GDTCORNetworkReachabilityFlags)currentFlags;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
59
Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Internal/GDTCORRegistrar.h
generated
Normal file
59
Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Internal/GDTCORRegistrar.h
generated
Normal file
@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright 2018 Google
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Internal/GDTCORMetricsControllerProtocol.h"
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Internal/GDTCORStorageProtocol.h"
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Internal/GDTCORUploader.h"
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORTargets.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/** Manages the registration of targets with the transport SDK. */
|
||||
@interface GDTCORRegistrar : NSObject <GDTCORLifecycleProtocol>
|
||||
|
||||
/** Creates and/or returns the singleton instance.
|
||||
*
|
||||
* @return The singleton instance of this class.
|
||||
*/
|
||||
+ (instancetype)sharedInstance;
|
||||
|
||||
/** Registers a backend implementation with the GoogleDataTransport infrastructure.
|
||||
*
|
||||
* @param backend The backend object to register with the given target.
|
||||
* @param target The target this backend object will be responsible for.
|
||||
*/
|
||||
- (void)registerUploader:(id<GDTCORUploader>)backend target:(GDTCORTarget)target;
|
||||
|
||||
/** Registers a storage implementation with the GoogleDataTransport infrastructure.
|
||||
*
|
||||
* @param storage The storage object to register with the given target.
|
||||
* @param target The target this storage object will be responsible for.
|
||||
*/
|
||||
- (void)registerStorage:(id<GDTCORStorageProtocol>)storage target:(GDTCORTarget)target;
|
||||
|
||||
/** Registers a metrics controller implementation with the GoogleDataTransport infrastructure.
|
||||
*
|
||||
* @param metricsController The metrics controller object to register with the given target.
|
||||
* @param target The target this metrics controller object will be responsible for.
|
||||
*/
|
||||
- (void)registerMetricsController:(id<GDTCORMetricsControllerProtocol>)metricsController
|
||||
target:(GDTCORTarget)target;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
61
Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Internal/GDTCORStorageEventSelector.h
generated
Normal file
61
Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Internal/GDTCORStorageEventSelector.h
generated
Normal file
@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright 2020 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORTargets.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/** This class enables the finding of events by matching events with the properties of this class.
|
||||
*/
|
||||
@interface GDTCORStorageEventSelector : NSObject
|
||||
|
||||
/** The target to find events for. Required. */
|
||||
@property(readonly, nonatomic) GDTCORTarget selectedTarget;
|
||||
|
||||
/** Finds a specific event. */
|
||||
@property(nullable, readonly, nonatomic) NSSet<NSString *> *selectedEventIDs;
|
||||
|
||||
/** Finds all events of a mappingID. */
|
||||
@property(nullable, readonly, nonatomic) NSSet<NSString *> *selectedMappingIDs;
|
||||
|
||||
/** Finds all events matching the qosTiers in this list. */
|
||||
@property(nullable, readonly, nonatomic) NSSet<NSNumber *> *selectedQosTiers;
|
||||
|
||||
/** Initializes an event selector that will find all events for the given target.
|
||||
*
|
||||
* @param target The selected target.
|
||||
* @return An immutable event selector instance.
|
||||
*/
|
||||
+ (instancetype)eventSelectorForTarget:(GDTCORTarget)target;
|
||||
|
||||
/** Instantiates an event selector.
|
||||
*
|
||||
* @param target The selected target.
|
||||
* @param eventIDs Optional param to find an event matching this eventID.
|
||||
* @param mappingIDs Optional param to find events matching this mappingID.
|
||||
* @param qosTiers Optional param to find events matching the given QoS tiers.
|
||||
* @return An immutable event selector instance.
|
||||
*/
|
||||
- (instancetype)initWithTarget:(GDTCORTarget)target
|
||||
eventIDs:(nullable NSSet<NSString *> *)eventIDs
|
||||
mappingIDs:(nullable NSSet<NSString *> *)mappingIDs
|
||||
qosTiers:(nullable NSSet<NSNumber *> *)qosTiers;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
210
Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Internal/GDTCORStorageProtocol.h
generated
Normal file
210
Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Internal/GDTCORStorageProtocol.h
generated
Normal file
@ -0,0 +1,210 @@
|
||||
/*
|
||||
* Copyright 2020 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Internal/GDTCORLifecycle.h"
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Internal/GDTCORStorageEventSelector.h"
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Internal/GDTCORStorageSizeBytes.h"
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORTargets.h"
|
||||
|
||||
@class GDTCOREvent;
|
||||
@class GDTCORClock;
|
||||
@class GDTCORUploadBatch;
|
||||
|
||||
@class FBLPromise<ValueType>;
|
||||
|
||||
@protocol GDTCORStorageDelegate;
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
typedef void (^GDTCORStorageBatchBlock)(NSNumber *_Nullable newBatchID,
|
||||
NSSet<GDTCOREvent *> *_Nullable batchEvents);
|
||||
|
||||
#pragma mark - GDTCORStorageProtocol
|
||||
|
||||
/** Defines the interface a storage subsystem is expected to implement. */
|
||||
@protocol GDTCORStorageProtocol <NSObject, GDTCORLifecycleProtocol>
|
||||
|
||||
/// The object that acts as the delegate of the storage instance.
|
||||
@property(nonatomic, weak, nullable) id<GDTCORStorageDelegate> delegate;
|
||||
|
||||
@required
|
||||
|
||||
/** Stores an event and calls onComplete with a non-nil error if anything went wrong.
|
||||
*
|
||||
* @param event The event to store
|
||||
* @param completion The completion block to call after an attempt to store the event has been made.
|
||||
*/
|
||||
- (void)storeEvent:(GDTCOREvent *)event
|
||||
onComplete:(void (^_Nullable)(BOOL wasWritten, NSError *_Nullable error))completion;
|
||||
|
||||
/** Returns YES if some events have been stored for the given target, NO otherwise.
|
||||
*
|
||||
* @param onComplete The completion block to invoke when determining if there are events is done.
|
||||
*/
|
||||
- (void)hasEventsForTarget:(GDTCORTarget)target onComplete:(void (^)(BOOL hasEvents))onComplete;
|
||||
|
||||
/** Constructs an event batch with the given event selector. Events in this batch will not be
|
||||
* returned in any queries or other batches until the batch is removed.
|
||||
*
|
||||
* @param eventSelector The event selector used to find the events.
|
||||
* @param expiration The expiration time of the batch. If removeBatchWithID:deleteEvents:onComplete:
|
||||
* is not called within this time frame, the batch will be removed with its events deleted.
|
||||
* @param onComplete The completion handler to be called when the events have been fetched.
|
||||
*/
|
||||
- (void)batchWithEventSelector:(nonnull GDTCORStorageEventSelector *)eventSelector
|
||||
batchExpiration:(nonnull NSDate *)expiration
|
||||
onComplete:(nonnull GDTCORStorageBatchBlock)onComplete;
|
||||
|
||||
/** Removes the event batch.
|
||||
*
|
||||
* @param batchID The batchID to remove.
|
||||
* @param deleteEvents If YES, the events in this batch are deleted.
|
||||
* @param onComplete The completion handler to call when the batch removal process has completed.
|
||||
*/
|
||||
- (void)removeBatchWithID:(NSNumber *)batchID
|
||||
deleteEvents:(BOOL)deleteEvents
|
||||
onComplete:(void (^_Nullable)(void))onComplete;
|
||||
|
||||
/** Finds the batchIDs for the given target and calls the callback block.
|
||||
*
|
||||
* @param target The target.
|
||||
* @param onComplete The block to invoke with the set of current batchIDs.
|
||||
*/
|
||||
- (void)batchIDsForTarget:(GDTCORTarget)target
|
||||
onComplete:(void (^)(NSSet<NSNumber *> *_Nullable batchIDs))onComplete;
|
||||
|
||||
/** Checks the storage for expired events and batches, deletes them if they're expired. */
|
||||
- (void)checkForExpirations;
|
||||
|
||||
/** Persists the given data with the given key.
|
||||
*
|
||||
* @param data The data to store.
|
||||
* @param key The unique key to store it to.
|
||||
* @param onComplete An block to be run when storage of the data is complete.
|
||||
*/
|
||||
- (void)storeLibraryData:(NSData *)data
|
||||
forKey:(NSString *)key
|
||||
onComplete:(nullable void (^)(NSError *_Nullable error))onComplete;
|
||||
|
||||
/** Retrieves the stored data for the given key and optionally sets a new value.
|
||||
*
|
||||
* @param key The key corresponding to the desired data.
|
||||
* @param onFetchComplete The callback to invoke with the data once it's retrieved.
|
||||
* @param setValueBlock This optional block can provide a new value to set.
|
||||
*/
|
||||
- (void)libraryDataForKey:(nonnull NSString *)key
|
||||
onFetchComplete:(nonnull void (^)(NSData *_Nullable data,
|
||||
NSError *_Nullable error))onFetchComplete
|
||||
setNewValue:(NSData *_Nullable (^_Nullable)(void))setValueBlock;
|
||||
|
||||
/** Removes data from storage and calls the callback when complete.
|
||||
*
|
||||
* @param key The key of the data to remove.
|
||||
* @param onComplete The callback that will be invoked when removing the data is complete.
|
||||
*/
|
||||
- (void)removeLibraryDataForKey:(NSString *)key
|
||||
onComplete:(void (^)(NSError *_Nullable error))onComplete;
|
||||
|
||||
/** Calculates and returns the total disk size that this storage consumes.
|
||||
*
|
||||
* @param onComplete The callback that will be invoked once storage size calculation is complete.
|
||||
*/
|
||||
- (void)storageSizeWithCallback:(void (^)(GDTCORStorageSizeBytes storageSize))onComplete;
|
||||
|
||||
@end
|
||||
|
||||
#pragma mark - GDTCORStoragePromiseProtocol
|
||||
|
||||
// TODO(ncooke3): Consider complete replacing block based API by promise API.
|
||||
|
||||
@class GDTCORMetricsMetadata;
|
||||
@class GDTCORStorageMetadata;
|
||||
|
||||
/** Promise based version of API defined in GDTCORStorageProtocol. See API docs for corresponding
|
||||
* methods in GDTCORStorageProtocol. */
|
||||
@protocol GDTCORStoragePromiseProtocol <GDTCORStorageProtocol>
|
||||
|
||||
- (FBLPromise<NSSet<NSNumber *> *> *)batchIDsForTarget:(GDTCORTarget)target;
|
||||
|
||||
- (FBLPromise<NSNull *> *)removeBatchWithID:(NSNumber *)batchID deleteEvents:(BOOL)deleteEvents;
|
||||
|
||||
- (FBLPromise<NSNull *> *)removeBatchesWithIDs:(NSSet<NSNumber *> *)batchIDs
|
||||
deleteEvents:(BOOL)deleteEvents;
|
||||
|
||||
- (FBLPromise<NSNull *> *)removeAllBatchesForTarget:(GDTCORTarget)target
|
||||
deleteEvents:(BOOL)deleteEvents;
|
||||
|
||||
/// Fetches metrics metadata from storage, passes them to the given handler, and writes the
|
||||
/// resulting metrics metadata from the given handler to storage.
|
||||
/// @note This API is thread-safe.
|
||||
/// @param handler A handler to process the fetch result and return an updated value to store.
|
||||
/// @return A promise that is fulfilled if the update is successful, and rejected otherwise.
|
||||
- (FBLPromise<NSNull *> *)fetchAndUpdateMetricsWithHandler:
|
||||
(GDTCORMetricsMetadata * (^)(GDTCORMetricsMetadata *_Nullable fetchedMetadata,
|
||||
NSError *_Nullable fetchError))handler;
|
||||
|
||||
/// Fetches and returns storage metadata.
|
||||
- (FBLPromise<GDTCORStorageMetadata *> *)fetchStorageMetadata;
|
||||
|
||||
/** See `hasEventsForTarget:onComplete:`.
|
||||
* @return A promise object that is resolved with @YES if there are events for the specified target
|
||||
* and @NO otherwise.
|
||||
*/
|
||||
- (FBLPromise<NSNumber *> *)hasEventsForTarget:(GDTCORTarget)target;
|
||||
|
||||
/** See `batchWithEventSelector:batchExpiration:onComplete:`
|
||||
* The promise is rejected when there are no events for the specified selector.
|
||||
*/
|
||||
- (FBLPromise<GDTCORUploadBatch *> *)batchWithEventSelector:
|
||||
(GDTCORStorageEventSelector *)eventSelector
|
||||
batchExpiration:(NSDate *)expiration;
|
||||
|
||||
@end
|
||||
|
||||
/** Retrieves the storage instance for the given target.
|
||||
*
|
||||
* @param target The target.
|
||||
* * @return The storage instance registered for the target, or nil if there is none.
|
||||
*/
|
||||
FOUNDATION_EXPORT
|
||||
id<GDTCORStorageProtocol> _Nullable GDTCORStorageInstanceForTarget(GDTCORTarget target);
|
||||
|
||||
FOUNDATION_EXPORT
|
||||
id<GDTCORStoragePromiseProtocol> _Nullable GDTCORStoragePromiseInstanceForTarget(
|
||||
GDTCORTarget target);
|
||||
|
||||
#pragma mark - GDTCORStorageDelegate
|
||||
|
||||
/// A type that can be delegated actions from a storage instance.
|
||||
@protocol GDTCORStorageDelegate <NSObject>
|
||||
|
||||
/// Tells the delegate that the storage instance has removed a set of expired events.
|
||||
/// @param storage The storage instance informing the delegate of this impending event.
|
||||
/// @param events A set of events that were removed from storage due to their expiration.
|
||||
- (void)storage:(id<GDTCORStorageProtocol>)storage
|
||||
didRemoveExpiredEvents:(NSSet<GDTCOREvent *> *)events;
|
||||
|
||||
/// Tells the delegate that the storage instance has dropped an event due to the event cache being
|
||||
/// full.
|
||||
/// @param storage The storage instance informing the delegate of this impending event.
|
||||
/// @param event An event that was dropped due to the event cache being full.
|
||||
- (void)storage:(id<GDTCORStorageProtocol>)storage didDropEvent:(GDTCOREvent *)event;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
18
Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Internal/GDTCORStorageSizeBytes.h
generated
Normal file
18
Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Internal/GDTCORStorageSizeBytes.h
generated
Normal file
@ -0,0 +1,18 @@
|
||||
// Copyright 2022 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
/// The data type to represent storage size.
|
||||
typedef uint64_t GDTCORStorageSizeBytes;
|
||||
59
Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Internal/GDTCORUploader.h
generated
Normal file
59
Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Internal/GDTCORUploader.h
generated
Normal file
@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright 2018 Google
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Internal/GDTCORLifecycle.h"
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORClock.h"
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORTargets.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/** Options that define a set of upload conditions. This is used to help minimize end user data
|
||||
* consumption impact.
|
||||
*/
|
||||
typedef NS_OPTIONS(NSInteger, GDTCORUploadConditions) {
|
||||
|
||||
/** An upload shouldn't be attempted, because there's no network. */
|
||||
GDTCORUploadConditionNoNetwork = 1 << 0,
|
||||
|
||||
/** An upload would likely use mobile data. */
|
||||
GDTCORUploadConditionMobileData = 1 << 1,
|
||||
|
||||
/** An upload would likely use wifi data. */
|
||||
GDTCORUploadConditionWifiData = 1 << 2,
|
||||
|
||||
/** An upload uses some sort of network connection, but it's unclear which. */
|
||||
GDTCORUploadConditionUnclearConnection = 1 << 3,
|
||||
|
||||
/** A high priority event has occurred. */
|
||||
GDTCORUploadConditionHighPriority = 1 << 4,
|
||||
};
|
||||
|
||||
/** This protocol defines the common interface for uploader implementations. */
|
||||
@protocol GDTCORUploader <NSObject, GDTCORLifecycleProtocol>
|
||||
|
||||
@required
|
||||
|
||||
/** Uploads events to the backend using this specific backend's chosen format.
|
||||
*
|
||||
* @param conditions The conditions that the upload attempt is likely to occur under.
|
||||
*/
|
||||
- (void)uploadTarget:(GDTCORTarget)target withConditions:(GDTCORUploadConditions)conditions;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
27
Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCOREndpoints_Private.h
generated
Normal file
27
Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCOREndpoints_Private.h
generated
Normal file
@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright 2020 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCOREndpoints.h"
|
||||
|
||||
@interface GDTCOREndpoints ()
|
||||
|
||||
/** Returns the list of all the upload URLs used by the transport library.
|
||||
*
|
||||
* @return Map of the transport target and the URL used for uploading the events for that target.
|
||||
*/
|
||||
+ (NSDictionary<NSNumber *, NSURL *> *)uploadURLs;
|
||||
|
||||
@end
|
||||
33
Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCOREvent_Private.h
generated
Normal file
33
Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCOREvent_Private.h
generated
Normal file
@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright 2018 Google
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCOREvent.h"
|
||||
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORClock.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface GDTCOREvent ()
|
||||
|
||||
/** The unique ID of the event. This property is for testing only. */
|
||||
@property(nonatomic, readwrite) NSString *eventID;
|
||||
|
||||
/** Generates a unique event ID. */
|
||||
+ (NSString *)nextEventID;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
28
Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORFlatFileStorage+Promises.h
generated
Normal file
28
Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORFlatFileStorage+Promises.h
generated
Normal file
@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright 2020 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Private/GDTCORFlatFileStorage.h"
|
||||
|
||||
@class FBLPromise<ValueType>;
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/// The category extends `GDTCORFlatFileStorage` API with `GDTCORStoragePromiseProtocol` methods.
|
||||
@interface GDTCORFlatFileStorage (Promises) <GDTCORStoragePromiseProtocol>
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
158
Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORFlatFileStorage.h
generated
Normal file
158
Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORFlatFileStorage.h
generated
Normal file
@ -0,0 +1,158 @@
|
||||
/*
|
||||
* Copyright 2018 Google
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Internal/GDTCORLifecycle.h"
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Internal/GDTCORStorageEventSelector.h"
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Internal/GDTCORStorageProtocol.h"
|
||||
|
||||
@class GDTCOREvent;
|
||||
@class GDTCORUploadCoordinator;
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/** The event components eventID dictionary key. */
|
||||
FOUNDATION_EXPORT NSString *const kGDTCOREventComponentsEventIDKey;
|
||||
|
||||
/** The event components qosTier dictionary key. */
|
||||
FOUNDATION_EXPORT NSString *const kGDTCOREventComponentsQoSTierKey;
|
||||
|
||||
/** The event components mappingID dictionary key. */
|
||||
FOUNDATION_EXPORT NSString *const kGDTCOREventComponentsMappingIDKey;
|
||||
|
||||
/** The event components expirationDate dictionary key. */
|
||||
FOUNDATION_EXPORT NSString *const kGDTCOREventComponentsExpirationKey;
|
||||
|
||||
/** The batch components target dictionary key. */
|
||||
FOUNDATION_EXPORT NSString *const kGDTCORBatchComponentsTargetKey;
|
||||
|
||||
/** The batch components batchID dictionary key. */
|
||||
FOUNDATION_EXPORT NSString *const kGDTCORBatchComponentsBatchIDKey;
|
||||
|
||||
/** The batch components expiration dictionary key. */
|
||||
FOUNDATION_EXPORT NSString *const kGDTCORBatchComponentsExpirationKey;
|
||||
|
||||
/** The maximum allowed disk space taken by the stored data. */
|
||||
FOUNDATION_EXPORT const uint64_t kGDTCORFlatFileStorageSizeLimit;
|
||||
|
||||
FOUNDATION_EXPORT NSString *const GDTCORFlatFileStorageErrorDomain;
|
||||
|
||||
typedef NS_ENUM(NSInteger, GDTCORFlatFileStorageError) {
|
||||
GDTCORFlatFileStorageErrorSizeLimitReached = 0
|
||||
};
|
||||
|
||||
/** Manages the storage of events. This class is thread-safe.
|
||||
*
|
||||
* Event files will be stored as follows:
|
||||
* <app cache>/google-sdk-events/<classname>/gdt_event_data/<target>/<eventID>.<qosTier>.<mappingID>
|
||||
*
|
||||
* Library data will be stored as follows:
|
||||
* <app cache>/google-sdk-events/<classname>/gdt_library_data/<libraryDataKey>
|
||||
*
|
||||
* Batch data will be stored as follows:
|
||||
* <app
|
||||
* cache>/google-sdk-events/<classname>/gdt_batch_data/<target>.<batchID>/<eventID>.<qosTier>.<mappingID>
|
||||
*/
|
||||
@interface GDTCORFlatFileStorage : NSObject <GDTCORStorageProtocol, GDTCORLifecycleProtocol>
|
||||
|
||||
/** The queue on which all storage work will occur. */
|
||||
@property(nonatomic) dispatch_queue_t storageQueue;
|
||||
|
||||
/** The upload coordinator instance used by this storage instance. */
|
||||
@property(nonatomic) GDTCORUploadCoordinator *uploadCoordinator;
|
||||
|
||||
/** Creates and/or returns the storage singleton.
|
||||
*
|
||||
* @return The storage singleton.
|
||||
*/
|
||||
+ (instancetype)sharedInstance;
|
||||
|
||||
/** Returns the base directory under which all events will be stored.
|
||||
*
|
||||
* @return The base directory under which all events will be stored.
|
||||
*/
|
||||
+ (NSString *)eventDataStoragePath;
|
||||
|
||||
/** Returns the base directory under which all library data will be stored.
|
||||
*
|
||||
* @return The base directory under which all library data will be stored.
|
||||
*/
|
||||
+ (NSString *)libraryDataStoragePath;
|
||||
|
||||
/** Returns the base directory under which all batch data will be stored.
|
||||
*
|
||||
* @return The base directory under which all batch data will be stored.
|
||||
*/
|
||||
+ (NSString *)batchDataStoragePath;
|
||||
|
||||
/** */
|
||||
+ (NSString *)batchPathForTarget:(GDTCORTarget)target
|
||||
batchID:(NSNumber *)batchID
|
||||
expirationDate:(NSDate *)expirationDate;
|
||||
|
||||
/** Returns a constructed storage path based on the given values. This path may not exist.
|
||||
*
|
||||
* @param target The target, which is necessary to be given a path.
|
||||
* @param eventID The eventID.
|
||||
* @param qosTier The qosTier.
|
||||
* @param expirationDate The expirationDate as a 1970-relative time interval.
|
||||
* @param mappingID The mappingID.
|
||||
* @return The path representing the combination of the given parameters.
|
||||
*/
|
||||
+ (NSString *)pathForTarget:(GDTCORTarget)target
|
||||
eventID:(NSString *)eventID
|
||||
qosTier:(NSNumber *)qosTier
|
||||
expirationDate:(NSDate *)expirationDate
|
||||
mappingID:(NSString *)mappingID;
|
||||
|
||||
/** Returns extant paths that match all of the given parameters.
|
||||
*
|
||||
* @param eventIDs The list of eventIDs to look for, or nil for any.
|
||||
* @param qosTiers The list of qosTiers to look for, or nil for any.
|
||||
* @param mappingIDs The list of mappingIDs to look for, or nil for any.
|
||||
* @param onComplete The completion to call once the paths have been discovered.
|
||||
*/
|
||||
- (void)pathsForTarget:(GDTCORTarget)target
|
||||
eventIDs:(nullable NSSet<NSString *> *)eventIDs
|
||||
qosTiers:(nullable NSSet<NSNumber *> *)qosTiers
|
||||
mappingIDs:(nullable NSSet<NSString *> *)mappingIDs
|
||||
onComplete:(void (^)(NSSet<NSString *> *paths))onComplete;
|
||||
|
||||
/** Fetches the current batchID counter value from library storage, increments it, and sets the new
|
||||
* value. Returns nil if a batchID was not able to be created for some reason.
|
||||
*
|
||||
* @param onComplete A block to execute when creating the next batchID is complete.
|
||||
*/
|
||||
- (void)nextBatchID:(void (^)(NSNumber *_Nullable batchID))onComplete;
|
||||
|
||||
/** Constructs a dictionary of event filename components.
|
||||
*
|
||||
* @param fileName The event filename to split.
|
||||
* @return The dictionary of event component keys to their values.
|
||||
*/
|
||||
- (nullable NSDictionary<NSString *, id> *)eventComponentsFromFilename:(NSString *)fileName;
|
||||
|
||||
/** Constructs a dictionary of batch filename components.
|
||||
*
|
||||
* @param fileName The batch folder name to split.
|
||||
* @return The dictionary of batch component keys to their values.
|
||||
*/
|
||||
- (nullable NSDictionary<NSString *, id> *)batchComponentsFromFilename:(NSString *)fileName;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
53
Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORLogSourceMetrics.h
generated
Normal file
53
Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORLogSourceMetrics.h
generated
Normal file
@ -0,0 +1,53 @@
|
||||
// Copyright 2022 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Internal/GDTCOREventDropReason.h"
|
||||
|
||||
@class GDTCOREvent;
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/// A model object that tracks, per log source, the number of events dropped for a variety of
|
||||
/// reasons. An event is considered "dropped" when the event is no longer persisted by the SDK.
|
||||
@interface GDTCORLogSourceMetrics : NSObject <NSSecureCoding>
|
||||
|
||||
/// Creates an empty log source metrics instance.
|
||||
+ (instancetype)metrics;
|
||||
|
||||
/// Creates a log source metrics for a collection of events that were dropped for a given reason.
|
||||
/// @param events The collection of events that were dropped.
|
||||
/// @param reason The reason for which given events were dropped.
|
||||
+ (instancetype)metricsWithEvents:(NSArray<GDTCOREvent *> *)events
|
||||
droppedForReason:(GDTCOREventDropReason)reason;
|
||||
|
||||
/// This API is unavailable.
|
||||
- (instancetype)init NS_UNAVAILABLE;
|
||||
|
||||
/// Returns a log source metrics instance created by merging the receiving log
|
||||
/// source metrics with the given log source metrics.
|
||||
/// @param logSourceMetrics The given log source metrics to merge with.
|
||||
- (GDTCORLogSourceMetrics *)logSourceMetricsByMergingWithLogSourceMetrics:
|
||||
(GDTCORLogSourceMetrics *)logSourceMetrics;
|
||||
|
||||
/// Returns a Boolean value that indicates whether the receiving log source metrics is equal to
|
||||
/// the given log source metrics.
|
||||
/// @param otherLogSourceMetrics The log source metrics with which to compare the
|
||||
/// receiving log source metrics.
|
||||
- (BOOL)isEqualToLogSourceMetrics:(GDTCORLogSourceMetrics *)otherLogSourceMetrics;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
61
Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORMetrics.h
generated
Normal file
61
Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORMetrics.h
generated
Normal file
@ -0,0 +1,61 @@
|
||||
// Copyright 2022 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCOREventDataObject.h"
|
||||
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Internal/GDTCORStorageSizeBytes.h"
|
||||
|
||||
@class GDTCORLogSourceMetrics;
|
||||
@class GDTCORMetricsMetadata;
|
||||
@class GDTCORStorageMetadata;
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/// An object representing metrics that represent a snapshot of the SDK's state and performance.
|
||||
@interface GDTCORMetrics : NSObject
|
||||
|
||||
/// The start of the time window over which the metrics were collected.
|
||||
@property(nonatomic, readonly) NSDate *collectionStartDate;
|
||||
|
||||
/// The log source metrics associated with the metrics.
|
||||
@property(nonatomic, readonly) GDTCORLogSourceMetrics *logSourceMetrics;
|
||||
|
||||
/// The end of the time window over which the metrics were collected.
|
||||
@property(nonatomic, readonly) NSDate *collectionEndDate;
|
||||
|
||||
/// The number of bytes the event cache was consuming in storage.
|
||||
@property(nonatomic, readonly) GDTCORStorageSizeBytes currentCacheSize;
|
||||
|
||||
/// The maximum number of bytes that the event cache is allowed to grow.
|
||||
@property(nonatomic, readonly) GDTCORStorageSizeBytes maxCacheSize;
|
||||
|
||||
/// The bundle ID associated with the metrics being collected.
|
||||
@property(nonatomic, readonly) NSString *bundleID;
|
||||
|
||||
/// Creates a metrics instance with the provided metadata.
|
||||
/// @param metricsMetadata The provided metrics metadata.
|
||||
/// @param storageMetadata The provided storage metadata.
|
||||
+ (instancetype)metricsWithMetricsMetadata:(GDTCORMetricsMetadata *)metricsMetadata
|
||||
storageMetadata:(GDTCORStorageMetadata *)storageMetadata;
|
||||
|
||||
/// Returns a Boolean value that indicates whether the receiving metrics is equal to the given
|
||||
/// metrics.
|
||||
/// @param otherMetrics The metrics with which to compare the receiving metrics.
|
||||
- (BOOL)isEqualToMetrics:(GDTCORMetrics *)otherMetrics;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
37
Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORMetricsController.h
generated
Normal file
37
Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORMetricsController.h
generated
Normal file
@ -0,0 +1,37 @@
|
||||
// Copyright 2022 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Internal/GDTCORMetricsControllerProtocol.h"
|
||||
|
||||
@protocol GDTCORStoragePromiseProtocol;
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface GDTCORMetricsController : NSObject <GDTCORMetricsControllerProtocol>
|
||||
|
||||
/// Returns the event metrics controller singleton.
|
||||
+ (instancetype)sharedInstance;
|
||||
|
||||
/// Designated initializer.
|
||||
/// @param storage The storage object to read and write metrics data from.
|
||||
- (instancetype)initWithStorage:(id<GDTCORStoragePromiseProtocol>)storage NS_DESIGNATED_INITIALIZER;
|
||||
|
||||
/// This API is unavailable.
|
||||
- (instancetype)init NS_UNAVAILABLE;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
50
Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORMetricsMetadata.h
generated
Normal file
50
Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORMetricsMetadata.h
generated
Normal file
@ -0,0 +1,50 @@
|
||||
// Copyright 2022 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Internal/GDTCOREventDropReason.h"
|
||||
|
||||
@class GDTCORLogSourceMetrics;
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/// An encodable model object that contains metadata that is persisted in storage until ready to be
|
||||
/// used to create a ``GDTCORMetrics`` instance.
|
||||
@interface GDTCORMetricsMetadata : NSObject <NSSecureCoding>
|
||||
|
||||
/// The start of the time window over which the metrics were collected.
|
||||
@property(nonatomic, copy, readonly) NSDate *collectionStartDate;
|
||||
|
||||
/// The log source metrics associated with the metrics.
|
||||
@property(nonatomic, copy, readonly) GDTCORLogSourceMetrics *logSourceMetrics;
|
||||
|
||||
/// Creates a metrics metadata object with the provided information.
|
||||
/// @param collectedSinceDate The start of the time window over which the metrics were collected.
|
||||
/// @param logSourceMetrics The metrics object that tracks metrics for each log source.
|
||||
+ (instancetype)metadataWithCollectionStartDate:(NSDate *)collectedSinceDate
|
||||
logSourceMetrics:(GDTCORLogSourceMetrics *)logSourceMetrics;
|
||||
|
||||
/// This API is unavailable.
|
||||
- (instancetype)init NS_UNAVAILABLE;
|
||||
|
||||
/// Returns a Boolean value that indicates whether the receiving metrics metadata is equal to
|
||||
/// the given metrics metadata.
|
||||
/// @param otherMetricsMetadata The metrics metadata with which to compare the
|
||||
/// receiving metrics metadata.
|
||||
- (BOOL)isEqualToMetricsMetadata:(GDTCORMetricsMetadata *)otherMetricsMetadata;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
30
Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORReachability_Private.h
generated
Normal file
30
Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORReachability_Private.h
generated
Normal file
@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright 2019 Google
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Internal/GDTCORReachability.h"
|
||||
|
||||
@interface GDTCORReachability ()
|
||||
|
||||
/** Allows manually setting the flags for testing purposes. */
|
||||
@property(nonatomic, readwrite) GDTCORNetworkReachabilityFlags flags;
|
||||
|
||||
/** Creates/returns the singleton instance of this class.
|
||||
*
|
||||
* @return The singleton instance of this class.
|
||||
*/
|
||||
+ (instancetype)sharedInstance;
|
||||
|
||||
@end
|
||||
39
Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORRegistrar_Private.h
generated
Normal file
39
Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORRegistrar_Private.h
generated
Normal file
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright 2018 Google
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Internal/GDTCORRegistrar.h"
|
||||
|
||||
@interface GDTCORRegistrar ()
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/** The concurrent queue on which all registration occurs. */
|
||||
@property(nonatomic, readonly) dispatch_queue_t registrarQueue;
|
||||
|
||||
/** A map of targets to backend implementations. */
|
||||
@property(atomic, readonly) NSMutableDictionary<NSNumber *, id<GDTCORUploader>> *targetToUploader;
|
||||
|
||||
/** A map of targets to storage instances. */
|
||||
@property(atomic, readonly)
|
||||
NSMutableDictionary<NSNumber *, id<GDTCORStorageProtocol>> *targetToStorage;
|
||||
|
||||
/** A map of targets to metrics controller instances. */
|
||||
@property(atomic, readonly)
|
||||
NSMutableDictionary<NSNumber *, id<GDTCORMetricsControllerProtocol>> *targetToMetricsController;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
41
Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORStorageMetadata.h
generated
Normal file
41
Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORStorageMetadata.h
generated
Normal file
@ -0,0 +1,41 @@
|
||||
// Copyright 2022 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Internal/GDTCORStorageSizeBytes.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/// A model object that contains metadata about the current state of the SDK's storage container.
|
||||
@interface GDTCORStorageMetadata : NSObject
|
||||
|
||||
/// The number of bytes the event cache is consuming in storage.
|
||||
@property(nonatomic, readonly) GDTCORStorageSizeBytes currentCacheSize;
|
||||
|
||||
/// The maximum number of bytes that the event cache may consume in storage.
|
||||
@property(nonatomic, readonly) GDTCORStorageSizeBytes maxCacheSize;
|
||||
|
||||
/// Creates a storage metadata object with the provided information.
|
||||
/// @param currentCacheSize The current number of bytes the event cache is consuming.
|
||||
/// @param maxCacheSize The current maximum capacity (in bytes) that the event cache may consume.
|
||||
+ (instancetype)metadataWithCurrentCacheSize:(GDTCORStorageSizeBytes)currentCacheSize
|
||||
maxCacheSize:(GDTCORStorageSizeBytes)maxCacheSize;
|
||||
|
||||
/// This API is unavailable.
|
||||
- (instancetype)init NS_UNAVAILABLE;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
57
Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORTransformer.h
generated
Normal file
57
Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORTransformer.h
generated
Normal file
@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright 2018 Google
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Internal/GDTCORLifecycle.h"
|
||||
|
||||
@class GDTCOREvent;
|
||||
|
||||
@protocol GDTCOREventTransformer;
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/** Manages the transforming of events. It's desirable for this to be its own class
|
||||
* because running all events through a single instance ensures that transformers are thread-safe.
|
||||
* Having a per-transport queue to run on isn't sufficient because transformer objects could
|
||||
* maintain state (or at least, there's nothing to stop them from doing that) and the same instances
|
||||
* may be used across multiple instances.
|
||||
*/
|
||||
@interface GDTCORTransformer : NSObject <GDTCORLifecycleProtocol>
|
||||
|
||||
/** Instantiates or returns the event transformer singleton.
|
||||
*
|
||||
* @return The singleton instance of the event transformer.
|
||||
*/
|
||||
+ (instancetype)sharedInstance;
|
||||
|
||||
/** Writes the result of applying the given transformers' `transformGDTEvent:` method on the given
|
||||
* event.
|
||||
*
|
||||
* @note If the app is suspended, a background task will be created to complete work in-progress,
|
||||
* but this method will not send any further events until the app is resumed.
|
||||
*
|
||||
* @param event The event to apply transformers on.
|
||||
* @param transformers The list of transformers to apply.
|
||||
* @param completion A block to run when an event was written to disk or dropped.
|
||||
*/
|
||||
- (void)transformEvent:(GDTCOREvent *)event
|
||||
withTransformers:(nullable NSArray<id<GDTCOREventTransformer>> *)transformers
|
||||
onComplete:(void (^_Nullable)(BOOL wasWritten, NSError *_Nullable error))completion;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
37
Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORTransformer_Private.h
generated
Normal file
37
Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORTransformer_Private.h
generated
Normal file
@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright 2020 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Private/GDTCORTransformer.h"
|
||||
|
||||
@protocol GDTCORApplicationProtocol;
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface GDTCORTransformer ()
|
||||
|
||||
/** The queue on which all work will occur. */
|
||||
@property(nonatomic) dispatch_queue_t eventWritingQueue;
|
||||
|
||||
/** The application instance that is used to begin/end background tasks. */
|
||||
@property(nonatomic, readonly) id<GDTCORApplicationProtocol> application;
|
||||
|
||||
/** The internal initializer. Should be used in tests only to create an instance with a
|
||||
* particular(fake) application instance. */
|
||||
- (instancetype)initWithApplication:(id<GDTCORApplicationProtocol>)application;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
39
Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORTransport_Private.h
generated
Normal file
39
Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORTransport_Private.h
generated
Normal file
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright 2019 Google
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORTransport.h"
|
||||
|
||||
@class GDTCORTransformer;
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface GDTCORTransport ()
|
||||
|
||||
/** The mapping identifier that the target backend will use to map the transport bytes to proto. */
|
||||
@property(nonatomic) NSString *mappingID;
|
||||
|
||||
/** The transformers that will operate on events sent by this transport. */
|
||||
@property(nonatomic) NSArray<id<GDTCOREventTransformer>> *transformers;
|
||||
|
||||
/** The target backend of this transport. */
|
||||
@property(nonatomic) NSInteger target;
|
||||
|
||||
/** The transformer instance to used to transform events. Allows injecting a fake during testing. */
|
||||
@property(nonatomic) GDTCORTransformer *transformerInstance;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
37
Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORUploadBatch.h
generated
Normal file
37
Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORUploadBatch.h
generated
Normal file
@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright 2020 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@class GDTCOREvent;
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/// A data object representing a batch of events scheduled for upload.
|
||||
@interface GDTCORUploadBatch : NSObject
|
||||
|
||||
/// An ID used to identify the batch in the storage.
|
||||
@property(nonatomic, readonly) NSNumber *batchID;
|
||||
|
||||
/// The collection of the events in the batch.
|
||||
@property(nonatomic, readonly) NSSet<GDTCOREvent *> *events;
|
||||
|
||||
/// The default initializer. See also docs for the corresponding properties.
|
||||
- (instancetype)initWithBatchID:(NSNumber *)batchID events:(NSSet<GDTCOREvent *> *)events;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
68
Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORUploadCoordinator.h
generated
Normal file
68
Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORUploadCoordinator.h
generated
Normal file
@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright 2018 Google
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Internal/GDTCORLifecycle.h"
|
||||
#import "GoogleDataTransport/GDTCORLibrary/Internal/GDTCORRegistrar.h"
|
||||
|
||||
@class GDTCORClock;
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/** This class connects storage and uploader implementations, providing events to an uploader
|
||||
* and informing the storage what events were successfully uploaded or not.
|
||||
*/
|
||||
@interface GDTCORUploadCoordinator : NSObject <GDTCORLifecycleProtocol>
|
||||
|
||||
/** The queue on which all upload coordination will occur. Also used by a dispatch timer. */
|
||||
/** Creates and/or returrns the singleton.
|
||||
*
|
||||
* @return The singleton instance of this class.
|
||||
*/
|
||||
+ (instancetype)sharedInstance;
|
||||
|
||||
/** The queue on which all upload coordination will occur. */
|
||||
@property(nonatomic, readonly) dispatch_queue_t coordinationQueue;
|
||||
|
||||
/** A timer that will causes regular checks for events to upload. */
|
||||
@property(nonatomic, readonly, nullable) dispatch_source_t timer;
|
||||
|
||||
/** The interval the timer will fire. */
|
||||
@property(nonatomic, readonly) uint64_t timerInterval;
|
||||
|
||||
/** Some leeway given to libdispatch for the timer interval event. */
|
||||
@property(nonatomic, readonly) uint64_t timerLeeway;
|
||||
|
||||
/** The registrar object the coordinator will use. Generally used for testing. */
|
||||
@property(nonatomic) GDTCORRegistrar *registrar;
|
||||
|
||||
/** Forces the backend specified by the target to upload the provided set of events. This should
|
||||
* only ever happen when the QoS tier of an event requires it.
|
||||
*
|
||||
* @param target The target that should force an upload.
|
||||
*/
|
||||
- (void)forceUploadForTarget:(GDTCORTarget)target;
|
||||
|
||||
/** Starts the upload timer. */
|
||||
- (void)startTimer;
|
||||
|
||||
/** Stops the upload timer from running. */
|
||||
- (void)stopTimer;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
66
Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORClock.h
generated
Normal file
66
Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORClock.h
generated
Normal file
@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright 2018 Google
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/** This class manages the device clock and produces snapshots of the current time. */
|
||||
@interface GDTCORClock : NSObject <NSSecureCoding>
|
||||
|
||||
/** The wallclock time, UTC, in milliseconds. */
|
||||
@property(nonatomic, readonly) int64_t timeMillis;
|
||||
|
||||
/** The offset from UTC in seconds. */
|
||||
@property(nonatomic, readonly) int64_t timezoneOffsetSeconds;
|
||||
|
||||
/** The kernel boot time when this clock was created in nanoseconds. */
|
||||
@property(nonatomic, readonly) int64_t kernelBootTimeNanoseconds;
|
||||
|
||||
/** The device uptime when this clock was created in nanoseconds. */
|
||||
@property(nonatomic, readonly) int64_t uptimeNanoseconds;
|
||||
|
||||
@property(nonatomic, readonly) int64_t kernelBootTime DEPRECATED_MSG_ATTRIBUTE(
|
||||
"Please use `kernelBootTimeNanoseconds` instead");
|
||||
|
||||
@property(nonatomic, readonly)
|
||||
int64_t uptime DEPRECATED_MSG_ATTRIBUTE("Please use `uptimeNanoseconds` instead");
|
||||
|
||||
/** Creates a GDTCORClock object using the current time and offsets.
|
||||
*
|
||||
* @return A new GDTCORClock object representing the current time state.
|
||||
*/
|
||||
+ (instancetype)snapshot;
|
||||
|
||||
/** Creates a GDTCORClock object representing a time in the future, relative to now.
|
||||
*
|
||||
* @param millisInTheFuture The millis in the future from now this clock should represent.
|
||||
* @return An instance representing a future time.
|
||||
*/
|
||||
+ (instancetype)clockSnapshotInTheFuture:(uint64_t)millisInTheFuture;
|
||||
|
||||
/** Compares one clock with another, returns YES if the caller is after the parameter.
|
||||
*
|
||||
* @return YES if the calling clock's time is after the given clock's time.
|
||||
*/
|
||||
- (BOOL)isAfter:(GDTCORClock *)otherClock;
|
||||
|
||||
/** Returns value of `uptime` property in milliseconds. */
|
||||
- (int64_t)uptimeMilliseconds;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@ -0,0 +1,144 @@
|
||||
/*
|
||||
* Copyright 2018 Google
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
/** The current logging level. This value and higher will be printed. Declared as volatile to make
|
||||
* getting and setting atomic.
|
||||
*/
|
||||
FOUNDATION_EXPORT volatile NSInteger GDTCORConsoleLoggerLoggingLevel;
|
||||
|
||||
/** A list of logging levels that GDT supports. */
|
||||
typedef NS_ENUM(NSInteger, GDTCORLoggingLevel) {
|
||||
|
||||
/** Causes all logs to be printed. */
|
||||
GDTCORLoggingLevelDebug = 1,
|
||||
|
||||
/** Causes all non-debug logs to be printed. */
|
||||
GDTCORLoggingLevelVerbose = 2,
|
||||
|
||||
/** Causes warnings and errors to be printed. */
|
||||
GDTCORLoggingLevelWarnings = 3,
|
||||
|
||||
/** Causes errors to be printed. This is the default value. */
|
||||
GDTCORLoggingLevelErrors = 4
|
||||
};
|
||||
|
||||
/** A list of message codes to print in the logger that help to correspond printed messages with
|
||||
* code locations.
|
||||
*
|
||||
* Prefixes:
|
||||
* - MCD => MessageCodeDebug
|
||||
* - MCW => MessageCodeWarning
|
||||
* - MCE => MessageCodeError
|
||||
*/
|
||||
typedef NS_ENUM(NSInteger, GDTCORMessageCode) {
|
||||
|
||||
/** For debug logs. */
|
||||
GDTCORMCDDebugLog = 0,
|
||||
|
||||
/** For warning messages concerning transportBytes: not being implemented by a data object. */
|
||||
GDTCORMCWDataObjectMissingBytesImpl = 1,
|
||||
|
||||
/** For warning messages concerning a failed event upload. */
|
||||
GDTCORMCWUploadFailed = 2,
|
||||
|
||||
/** For warning messages concerning a forced event upload. */
|
||||
GDTCORMCWForcedUpload = 3,
|
||||
|
||||
/** For warning messages concerning a failed reachability call. */
|
||||
GDTCORMCWReachabilityFailed = 4,
|
||||
|
||||
/** For warning messages concerning a database warning. */
|
||||
GDTCORMCWDatabaseWarning = 5,
|
||||
|
||||
/** For warning messages concerning the reading of a event file. */
|
||||
GDTCORMCWFileReadError = 6,
|
||||
|
||||
/** For error messages concerning transformGDTEvent: not being implemented by an event
|
||||
transformer. */
|
||||
GDTCORMCETransformerDoesntImplementTransform = 1000,
|
||||
|
||||
/** For error messages concerning the creation of a directory failing. */
|
||||
GDTCORMCEDirectoryCreationError = 1001,
|
||||
|
||||
/** For error messages concerning the writing of a event file. */
|
||||
GDTCORMCEFileWriteError = 1002,
|
||||
|
||||
/** For error messages concerning the lack of a prioritizer for a given backend. */
|
||||
GDTCORMCEPrioritizerError = 1003,
|
||||
|
||||
/** For error messages concerning a package delivery API violation. */
|
||||
GDTCORMCEDeliverTwice = 1004,
|
||||
|
||||
/** For error messages concerning an error in an implementation of -transportBytes. */
|
||||
GDTCORMCETransportBytesError = 1005,
|
||||
|
||||
/** For general purpose error messages in a dependency. */
|
||||
GDTCORMCEGeneralError = 1006,
|
||||
|
||||
/** For fatal errors. Please go to https://github.com/firebase/firebase-ios-sdk/issues and open
|
||||
* an issue if you encounter an error with this code.
|
||||
*/
|
||||
GDTCORMCEFatalAssertion = 1007,
|
||||
|
||||
/** For error messages concerning the reading of a event file. */
|
||||
GDTCORMCEFileReadError = 1008,
|
||||
|
||||
/** For errors related to running sqlite. */
|
||||
GDTCORMCEDatabaseError = 1009,
|
||||
};
|
||||
|
||||
/** Prints the given code and format string to the console.
|
||||
*
|
||||
* @param code The message code describing the nature of the log.
|
||||
* @param logLevel The log level of this log.
|
||||
* @param format The format string.
|
||||
*/
|
||||
FOUNDATION_EXPORT
|
||||
void GDTCORLog(GDTCORMessageCode code, GDTCORLoggingLevel logLevel, NSString *_Nonnull format, ...)
|
||||
NS_FORMAT_FUNCTION(3, 4);
|
||||
|
||||
/** Prints an assert log to the console.
|
||||
*
|
||||
* @param wasFatal Send YES if the assertion should be fatal, NO otherwise.
|
||||
* @param file The file in which the failure occurred.
|
||||
* @param line The line number of the failure.
|
||||
* @param format The format string.
|
||||
*/
|
||||
FOUNDATION_EXPORT void GDTCORLogAssert(BOOL wasFatal,
|
||||
NSString *_Nonnull file,
|
||||
NSInteger line,
|
||||
NSString *_Nullable format,
|
||||
...) NS_FORMAT_FUNCTION(4, 5);
|
||||
|
||||
/** Returns the string that represents some message code.
|
||||
*
|
||||
* @param code The code to convert to a string.
|
||||
* @return The string representing the message code.
|
||||
*/
|
||||
FOUNDATION_EXPORT NSString *_Nonnull GDTCORMessageCodeEnumToString(GDTCORMessageCode code);
|
||||
|
||||
#define GDTCORLogDebug(MESSAGE_FORMAT, ...) \
|
||||
GDTCORLog(GDTCORMCDDebugLog, GDTCORLoggingLevelDebug, MESSAGE_FORMAT, __VA_ARGS__);
|
||||
|
||||
// A define to wrap GULLogWarning with slightly more convenient usage.
|
||||
#define GDTCORLogWarning(MESSAGE_CODE, MESSAGE_FORMAT, ...) \
|
||||
GDTCORLog(MESSAGE_CODE, GDTCORLoggingLevelWarnings, MESSAGE_FORMAT, __VA_ARGS__);
|
||||
|
||||
// A define to wrap GULLogError with slightly more convenient usage and a failing assert.
|
||||
#define GDTCORLogError(MESSAGE_CODE, MESSAGE_FORMAT, ...) \
|
||||
GDTCORLog(MESSAGE_CODE, GDTCORLoggingLevelErrors, MESSAGE_FORMAT, __VA_ARGS__);
|
||||
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright 2018 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "GDTCORTargets.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/* Class that manages the endpoints used by Google data transport library. */
|
||||
@interface GDTCOREndpoints : NSObject
|
||||
|
||||
- (instancetype)init NS_UNAVAILABLE;
|
||||
|
||||
/** Returns the upload URL for a target specified. If the target is not available, returns nil.
|
||||
*
|
||||
* @param target GoogleDataTransport target for which the upload URL is being looked up for.
|
||||
* @return URL that will be used for uploading the events for the provided target.
|
||||
*/
|
||||
+ (nullable NSURL *)uploadURLForTarget:(GDTCORTarget)target;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
102
Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCOREvent.h
generated
Normal file
102
Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCOREvent.h
generated
Normal file
@ -0,0 +1,102 @@
|
||||
/*
|
||||
* Copyright 2018 Google
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "GDTCOREventDataObject.h"
|
||||
#import "GDTCORTargets.h"
|
||||
|
||||
@class GDTCORClock;
|
||||
@class GDTCORProductData;
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/** The different possible quality of service specifiers. High values indicate high priority. */
|
||||
typedef NS_ENUM(NSInteger, GDTCOREventQoS) {
|
||||
/** The QoS tier wasn't set, and won't ever be sent. */
|
||||
GDTCOREventQoSUnknown = 0,
|
||||
|
||||
/** This event is internal telemetry data that should not be sent on its own if possible. */
|
||||
GDTCOREventQoSTelemetry = 1,
|
||||
|
||||
/** This event should be sent, but in a batch only roughly once per day. */
|
||||
GDTCOREventQoSDaily = 2,
|
||||
|
||||
/** This event should be sent when requested by the uploader. */
|
||||
GDTCOREventQosDefault = 3,
|
||||
|
||||
/** This event should be sent immediately along with any other data that can be batched. */
|
||||
GDTCOREventQoSFast = 4,
|
||||
|
||||
/** This event should only be uploaded on wifi. */
|
||||
GDTCOREventQoSWifiOnly = 5,
|
||||
};
|
||||
|
||||
@interface GDTCOREvent : NSObject <NSSecureCoding>
|
||||
|
||||
/** The unique ID of the event. */
|
||||
@property(readonly, nonatomic) NSString *eventID;
|
||||
|
||||
/** The mapping identifier, to allow backends to map the transport bytes to a proto. */
|
||||
@property(nullable, readonly, nonatomic) NSString *mappingID;
|
||||
|
||||
/** The identifier for the backend this event will eventually be sent to. */
|
||||
@property(readonly, nonatomic) GDTCORTarget target;
|
||||
|
||||
/** The data object encapsulated in the transport of your choice, as long as it implements
|
||||
* the GDTCOREventDataObject protocol. */
|
||||
@property(nullable, nonatomic) id<GDTCOREventDataObject> dataObject;
|
||||
|
||||
/** The serialized bytes from calling [dataObject transportBytes]. */
|
||||
@property(nullable, readonly, nonatomic) NSData *serializedDataObjectBytes;
|
||||
|
||||
/** The quality of service tier this event belongs to. */
|
||||
@property(nonatomic) GDTCOREventQoS qosTier;
|
||||
|
||||
/** The clock snapshot at the time of the event. */
|
||||
@property(nonatomic) GDTCORClock *clockSnapshot;
|
||||
|
||||
/** The expiration date of the event. Default is 604800 seconds (7 days) from creation. */
|
||||
@property(nonatomic) NSDate *expirationDate;
|
||||
|
||||
/** Bytes that can be used by an uploader later on. */
|
||||
@property(nullable, nonatomic) NSData *customBytes;
|
||||
|
||||
/** The product data that the event is associated with, if any. */
|
||||
@property(nullable, readonly, nonatomic) GDTCORProductData *productData;
|
||||
|
||||
/** Initializes an instance using the given mapping ID and target.
|
||||
*
|
||||
* @param mappingID The mapping identifier.
|
||||
* @param target The event's target identifier.
|
||||
* @return An instance of this class.
|
||||
*/
|
||||
- (nullable instancetype)initWithMappingID:(NSString *)mappingID target:(GDTCORTarget)target;
|
||||
|
||||
/** Initializes an instance using the given mapping ID, product data, and target.
|
||||
*
|
||||
* @param mappingID The mapping identifier.
|
||||
* @param productData The product data to associate this event with.
|
||||
* @param target The event's target identifier.
|
||||
* @return An instance of this class.
|
||||
*/
|
||||
- (nullable instancetype)initWithMappingID:(NSString *)mappingID
|
||||
productData:(nullable GDTCORProductData *)productData
|
||||
target:(GDTCORTarget)target;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright 2018 Google
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/** This protocol defines the common interface that event protos should implement regardless of the
|
||||
* underlying transport technology (protobuf, nanopb, etc).
|
||||
*/
|
||||
@protocol GDTCOREventDataObject <NSObject>
|
||||
|
||||
@required
|
||||
|
||||
/** Returns the serialized proto bytes of the implementing event proto.
|
||||
*
|
||||
* @return the serialized proto bytes of the implementing event proto.
|
||||
*/
|
||||
- (NSData *)transportBytes;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright 2018 Google
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@class GDTCOREvent;
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/** Defines the API that event transformers must adopt. */
|
||||
@protocol GDTCOREventTransformer <NSObject>
|
||||
|
||||
@required
|
||||
|
||||
/** Transforms an event by applying some logic to it. Events returned can be nil, for example, in
|
||||
* instances where the event should be sampled.
|
||||
*
|
||||
* @param event The event to transform.
|
||||
* @return A transformed event, or nil if the transformation dropped the event.
|
||||
*/
|
||||
- (nullable GDTCOREvent *)transformGDTEvent:(GDTCOREvent *)event;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@ -0,0 +1,29 @@
|
||||
// Copyright 2023 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@interface GDTCORProductData : NSObject <NSCopying, NSSecureCoding>
|
||||
|
||||
/// The product ID.
|
||||
@property(nonatomic, readonly) int32_t productID;
|
||||
|
||||
/// Initializes an instance using the given product ID.
|
||||
/// - Parameter productID: A 32-bit integer.
|
||||
- (instancetype)initWithProductID:(int32_t)productID;
|
||||
|
||||
/// This API is unavailable.
|
||||
- (instancetype)init NS_UNAVAILABLE;
|
||||
|
||||
@end
|
||||
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright 2019 Google
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
/** The list of targets supported by the shared transport infrastructure.
|
||||
* These targets map to a specific backend designed to accept GDT payloads. If
|
||||
* adding a new target, please use the previous value +1.
|
||||
*/
|
||||
typedef NS_ENUM(NSInteger, GDTCORTarget) {
|
||||
|
||||
/** Target used for testing purposes. */
|
||||
kGDTCORTargetTest = 999,
|
||||
|
||||
/** Target used by internal clients. See go/firelog for more information. */
|
||||
kGDTCORTargetCCT = 1000,
|
||||
|
||||
/** Target mapping to the Firelog backend. See go/firelog for more information. */
|
||||
kGDTCORTargetFLL = 1001,
|
||||
|
||||
/** Special-purpose Crashlytics target. Please do not use it without permission. */
|
||||
kGDTCORTargetCSH = 1002,
|
||||
|
||||
/** Target used for integration testing. */
|
||||
kGDTCORTargetINT = 1003,
|
||||
};
|
||||
101
Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORTransport.h
generated
Normal file
101
Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORTransport.h
generated
Normal file
@ -0,0 +1,101 @@
|
||||
/*
|
||||
* Copyright 2018 Google
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "GDTCOREventTransformer.h"
|
||||
#import "GDTCORTargets.h"
|
||||
|
||||
@class GDTCOREvent;
|
||||
@class GDTCORProductData;
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface GDTCORTransport : NSObject
|
||||
|
||||
// Please use the designated initializer.
|
||||
- (instancetype)init NS_UNAVAILABLE;
|
||||
|
||||
/** Initializes a new transport that will send events to the given target backend.
|
||||
*
|
||||
* @param mappingID The mapping identifier used by the backend to map the data object transport
|
||||
* bytes to a proto.
|
||||
* @param transformers A list of transformers to be applied to events that are sent.
|
||||
* @param target The target backend of this transport.
|
||||
* @return A transport that will send events.
|
||||
*/
|
||||
- (nullable instancetype)initWithMappingID:(NSString *)mappingID
|
||||
transformers:
|
||||
(nullable NSArray<id<GDTCOREventTransformer>> *)transformers
|
||||
target:(GDTCORTarget)target NS_DESIGNATED_INITIALIZER;
|
||||
|
||||
/** Copies and sends an internal telemetry event. Events sent using this API are lower in priority,
|
||||
* and sometimes won't be sent on their own.
|
||||
*
|
||||
* @note This will convert the event's data object to data and release the original event.
|
||||
*
|
||||
* @param event The event to send.
|
||||
* @param completion A block that will be called when the event has been written or dropped.
|
||||
*/
|
||||
- (void)sendTelemetryEvent:(GDTCOREvent *)event
|
||||
onComplete:(void (^_Nullable)(BOOL wasWritten, NSError *_Nullable error))completion;
|
||||
|
||||
/** Copies and sends an internal telemetry event. Events sent using this API are lower in priority,
|
||||
* and sometimes won't be sent on their own.
|
||||
*
|
||||
* @note This will convert the event's data object to data and release the original event.
|
||||
*
|
||||
* @param event The event to send.
|
||||
*/
|
||||
- (void)sendTelemetryEvent:(GDTCOREvent *)event;
|
||||
|
||||
/** Copies and sends an SDK service data event. Events send using this API are higher in priority,
|
||||
* and will cause a network request at some point in the relative near future.
|
||||
*
|
||||
* @note This will convert the event's data object to data and release the original event.
|
||||
*
|
||||
* @param event The event to send.
|
||||
* @param completion A block that will be called when the event has been written or dropped.
|
||||
*/
|
||||
- (void)sendDataEvent:(GDTCOREvent *)event
|
||||
onComplete:(void (^_Nullable)(BOOL wasWritten, NSError *_Nullable error))completion;
|
||||
|
||||
/** Copies and sends an SDK service data event. Events send using this API are higher in priority,
|
||||
* and will cause a network request at some point in the relative near future.
|
||||
*
|
||||
* @note This will convert the event's data object to data and release the original event.
|
||||
*
|
||||
* @param event The event to send.
|
||||
*/
|
||||
- (void)sendDataEvent:(GDTCOREvent *)event;
|
||||
|
||||
/** Creates an event for use by this transport.
|
||||
*
|
||||
* @return An event that is suited for use by this transport.
|
||||
*/
|
||||
- (GDTCOREvent *)eventForTransport;
|
||||
|
||||
/**
|
||||
* Creates an event with the given product data for use by this transport.
|
||||
*
|
||||
* @param productData The given product data to associate with the created event.
|
||||
* @return An event that is suited for use by this transport.
|
||||
*/
|
||||
- (GDTCOREvent *)eventForTransportWithProductData:(nonnull GDTCORProductData *)productData;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright 2018 Google
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#import "GDTCORClock.h"
|
||||
#import "GDTCORConsoleLogger.h"
|
||||
#import "GDTCOREndpoints.h"
|
||||
#import "GDTCOREvent.h"
|
||||
#import "GDTCOREventDataObject.h"
|
||||
#import "GDTCOREventTransformer.h"
|
||||
#import "GDTCORProductData.h"
|
||||
#import "GDTCORTargets.h"
|
||||
#import "GDTCORTransport.h"
|
||||
30
Pods/GoogleDataTransport/GoogleDataTransport/Resources/PrivacyInfo.xcprivacy
generated
Normal file
30
Pods/GoogleDataTransport/GoogleDataTransport/Resources/PrivacyInfo.xcprivacy
generated
Normal file
@ -0,0 +1,30 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>NSPrivacyTracking</key>
|
||||
<false/>
|
||||
<key>NSPrivacyTrackingDomains</key>
|
||||
<array>
|
||||
</array>
|
||||
<key>NSPrivacyCollectedDataTypes</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>NSPrivacyCollectedDataType</key>
|
||||
<string>NSPrivacyCollectedDataTypeOtherDiagnosticData</string>
|
||||
<key>NSPrivacyCollectedDataTypeLinked</key>
|
||||
<false/>
|
||||
<key>NSPrivacyCollectedDataTypeTracking</key>
|
||||
<false/>
|
||||
<key>NSPrivacyCollectedDataTypePurposes</key>
|
||||
<array>
|
||||
<string>NSPrivacyCollectedDataTypePurposeAnalytics</string>
|
||||
</array>
|
||||
</dict>
|
||||
</array>
|
||||
<key>NSPrivacyAccessedAPITypes</key>
|
||||
<array>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
|
||||
202
Pods/GoogleDataTransport/LICENSE
generated
Normal file
202
Pods/GoogleDataTransport/LICENSE
generated
Normal file
@ -0,0 +1,202 @@
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
236
Pods/GoogleDataTransport/README.md
generated
Normal file
236
Pods/GoogleDataTransport/README.md
generated
Normal file
@ -0,0 +1,236 @@
|
||||
[](https://cocoapods.org/pods/GoogleDataTransport)
|
||||
[](https://cocoapods.org/pods/GoogleDataTransport)
|
||||
[](https://cocoapods.org/pods/GoogleDataTransport)
|
||||
|
||||
[![Actions Status][gh-datatransport-badge]][gh-actions]
|
||||
|
||||
# GoogleDataTransport
|
||||
|
||||
This library is for internal Google use only. It allows the logging of data and
|
||||
telemetry from Google SDKs.
|
||||
|
||||
## Integration Testing
|
||||
These instructions apply to minor and patch version updates. Major versions need
|
||||
a customized adaptation.
|
||||
|
||||
After the CI is green:
|
||||
* Determine the next version for release by checking the
|
||||
[tagged releases](https://github.com/google/GoogleDataTransport/tags).
|
||||
Ensure that the next release version keeps the Swift PM and CocoaPods versions in sync.
|
||||
* Verify that the releasing version is the latest entry in the [CHANGELOG.md](CHANGELOG.md),
|
||||
updating it if necessary.
|
||||
* Update the version in the podspec to match the latest entry in the [CHANGELOG.md](CHANGELOG.md)
|
||||
* Checkout the `main` branch and ensure it is up to date.
|
||||
```console
|
||||
git checkout main
|
||||
git pull
|
||||
```
|
||||
* Add the CocoaPods tag (`{version}` will be the latest version in the [podspec](GoogleDataTransport.podspec#L3))
|
||||
```console
|
||||
git tag CocoaPods-{version}
|
||||
git push origin CocoaPods-{version}
|
||||
```
|
||||
* Push the podspec to the designated repo
|
||||
* If this version of GDT is intended to launch **before or with** the next Firebase release:
|
||||
<details>
|
||||
<summary>Push to <b>SpecsStaging</b></summary>
|
||||
|
||||
```console
|
||||
pod repo push --skip-tests --use-json staging GoogleDataTransport.podspec
|
||||
```
|
||||
|
||||
If the command fails with `Unable to find the 'staging' repo.`, add the staging repo with:
|
||||
```console
|
||||
pod repo add staging git@github.com:firebase/SpecsStaging.git
|
||||
```
|
||||
</details>
|
||||
* Otherwise:
|
||||
<details>
|
||||
<summary>Push to <b>SpecsDev</b></summary>
|
||||
|
||||
```console
|
||||
pod repo push --skip-tests --use-json dev GoogleDataTransport.podspec
|
||||
```
|
||||
|
||||
If the command fails with `Unable to find the 'dev' repo.`, add the dev repo with:
|
||||
```console
|
||||
pod repo add dev git@github.com:firebase/SpecsDev.git
|
||||
```
|
||||
</details>
|
||||
* Run Firebase CI by waiting until next nightly or adding a PR that touches `Gemfile`.
|
||||
* On google3, create a workspace and new CL. Then copybara and run a global TAP.
|
||||
<pre>
|
||||
/google/data/ro/teams/copybara/copybara third_party/firebase/ios/Releases/GoogleDataTransport/copy.bara.sky \
|
||||
--piper-description-behavior=OVERWRITE \
|
||||
--destination-cl=<b>YOUR_CL</b> gdt
|
||||
</pre>
|
||||
|
||||
## Publishing
|
||||
The release process is as follows:
|
||||
1. [Tag and release for Swift PM](#swift-package-manager)
|
||||
2. [Publish to CocoaPods](#cocoapods)
|
||||
3. [Create GitHub Release](#create-github-release)
|
||||
4. [Perform post release cleanup](#post-release-cleanup)
|
||||
|
||||
### Swift Package Manager
|
||||
By creating and [pushing a tag](https://github.com/google/GoogleDataTransport/tags)
|
||||
for Swift PM, the newly tagged version will be immediately released for public use.
|
||||
Given this, please verify the intended time of release for Swift PM.
|
||||
* Add a version tag for Swift PM
|
||||
```console
|
||||
git tag {version}
|
||||
git push origin {version}
|
||||
```
|
||||
*Note: Ensure that any inflight PRs that depend on the new `GoogleDataTransport` version are updated to point to the
|
||||
newly tagged version rather than a checksum.*
|
||||
|
||||
### CocoaPods
|
||||
* Publish the newly versioned pod to CocoaPods
|
||||
|
||||
It's recommended to point to the `GoogleDataTransport.podspec` in `staging` to make sure the correct spec is being published.
|
||||
|
||||
> [!WARNING]
|
||||
> Manually update your local SpecsStaging clone or run `pod repo update`
|
||||
> before proceeding.
|
||||
|
||||
```console
|
||||
pod trunk push ~/.cocoapods/repos/staging/GoogleDataTransport/{version}/GoogleDataTransport.podspec.json --skip-tests
|
||||
```
|
||||
|
||||
The pod push was successful if the above command logs: `🚀 GoogleDataTransport ({version}) successfully published`.
|
||||
In addition, a new commit that publishes the new version (co-authored by [CocoaPodsAtGoogle](https://github.com/CocoaPodsAtGoogle))
|
||||
should appear in the [CocoaPods specs repo](https://github.com/CocoaPods/Specs). Last, the latest version should be displayed
|
||||
on [GoogleDataTransport's CocoaPods page](https://cocoapods.org/pods/GoogleDataTransport).
|
||||
|
||||
### [Create GitHub Release](https://github.com/google/GoogleDataTransport/releases/new/)
|
||||
Update the [release template](https://github.com/google/GoogleDataTransport/releases/new/)'s **Tag version** and **Release title**
|
||||
fields with the latest version. In addition, reference the [Release Notes](./CHANGELOG.md) in the release's description.
|
||||
|
||||
See [this release](https://github.com/google/GoogleDataTransport/releases/edit/9.0.1) for an example.
|
||||
|
||||
*Don't forget to perform the [post release cleanup](#post-release-cleanup)!*
|
||||
|
||||
### Post Release Cleanup
|
||||
<details>
|
||||
<summary>Clean up <b>SpecsStaging</b></summary>
|
||||
|
||||
```console
|
||||
pwd=$(pwd)
|
||||
mkdir -p /tmp/release-cleanup && cd $_
|
||||
git clone git@github.com:firebase/SpecsStaging.git
|
||||
cd SpecsStaging/
|
||||
git rm -rf GoogleDataTransport/
|
||||
git commit -m "Post publish cleanup"
|
||||
git push origin master
|
||||
rm -rf /tmp/release-cleanup
|
||||
cd $pwd
|
||||
```
|
||||
</details>
|
||||
|
||||
## Set logging level
|
||||
|
||||
### Swift
|
||||
|
||||
- Import `GoogleDataTransport` module:
|
||||
```swift
|
||||
import GoogleDataTransport
|
||||
```
|
||||
- Set logging level global variable to the desired value before calling `FirebaseApp.configure()`:
|
||||
```swift
|
||||
GDTCORConsoleLoggerLoggingLevel = GDTCORLoggingLevel.debug.rawValue
|
||||
```
|
||||
### Objective-C
|
||||
|
||||
- Import `GoogleDataTransport`:
|
||||
```objective-c
|
||||
#import <GoogleDataTransport/GoogleDataTransport.h>
|
||||
```
|
||||
- Set logging level global variable to the desired value before calling `-[FIRApp configure]`:
|
||||
```objective-c
|
||||
GDTCORConsoleLoggerLoggingLevel = GDTCORLoggingLevelDebug;
|
||||
```
|
||||
|
||||
## Prereqs
|
||||
|
||||
- `gem install --user cocoapods cocoapods-generate`
|
||||
- `brew install protobuf nanopb-generator`
|
||||
- `easy_install --user protobuf`
|
||||
|
||||
## To develop
|
||||
|
||||
- Run `./GoogleDataTransport/generate_project.sh` after installing the prereqs
|
||||
|
||||
## When adding new logging endpoint
|
||||
|
||||
- Use commands similar to:
|
||||
- `python -c "line='https://www.firebase.com'; print line[0::2]" `
|
||||
- `python -c "line='https://www.firebase.com'; print line[1::2]" `
|
||||
|
||||
## When adding internal code that shouldn't be easily usable on github
|
||||
|
||||
- Consider using go/copybara-library/scrubbing#cc_scrub
|
||||
|
||||
## Development
|
||||
|
||||
Ensure that you have at least the following software:
|
||||
|
||||
* Xcode 12.0 (or later)
|
||||
* CocoaPods 1.10.0 (or later)
|
||||
* [CocoaPods generate](https://github.com/square/cocoapods-generate)
|
||||
|
||||
For the pod that you want to develop:
|
||||
|
||||
`pod gen GoogleDataTransport.podspec --local-sources=./ --auto-open --platforms=ios`
|
||||
|
||||
Note: If the CocoaPods cache is out of date, you may need to run
|
||||
`pod repo update` before the `pod gen` command.
|
||||
|
||||
Note: Set the `--platforms` option to `macos` or `tvos` to develop/test for
|
||||
those platforms. Since 10.2, Xcode does not properly handle multi-platform
|
||||
CocoaPods workspaces.
|
||||
|
||||
### Development for Catalyst
|
||||
* `pod gen GoogleDataTransport.podspec --local-sources=./ --auto-open --platforms=ios`
|
||||
* Check the Mac box in the App-iOS Build Settings
|
||||
* Sign the App in the Settings Signing & Capabilities tab
|
||||
* Click Pods in the Project Manager
|
||||
* Add Signing to the iOS host app and unit test targets
|
||||
* Select the Unit-unit scheme
|
||||
* Run it to build and test
|
||||
|
||||
Alternatively disable signing in each target:
|
||||
* Go to Build Settings tab
|
||||
* Click `+`
|
||||
* Select `Add User-Defined Setting`
|
||||
* Add `CODE_SIGNING_REQUIRED` setting with a value of `NO`
|
||||
|
||||
### Code Formatting
|
||||
|
||||
To ensure that the code is formatted consistently, run the script
|
||||
[./scripts/check.sh](https://github.com/firebase/firebase-ios-sdk/blob/main/scripts/check.sh)
|
||||
before creating a PR.
|
||||
|
||||
GitHub Actions will verify that any code changes are done in a style compliant
|
||||
way. Install `clang-format` and `mint`:
|
||||
|
||||
```console
|
||||
brew install clang-format@18
|
||||
brew install mint
|
||||
```
|
||||
|
||||
### Running Unit Tests
|
||||
|
||||
Select a scheme and press Command-u to build a component and run its unit tests.
|
||||
|
||||
## Contributing
|
||||
|
||||
See [Contributing](CONTRIBUTING.md) for more information on contributing to the Firebase
|
||||
iOS SDK.
|
||||
|
||||
## License
|
||||
|
||||
The contents of this repository is licensed under the
|
||||
[Apache License, version 2.0](http://www.apache.org/licenses/LICENSE-2.0).
|
||||
|
||||
[gh-actions]: https://github.com/firebase/firebase-ios-sdk/actions
|
||||
[gh-datatransport-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/datatransport/badge.svg
|
||||
Reference in New Issue
Block a user