Skip to content

Merge googledatatransport to master #2829

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 47 commits into from
Apr 13, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
c22e2b7
Initial structural work for the google data logger. (#2162)
mikehaney24 Dec 8, 2018
546bf67
Add additional base infrastructure for the logging client (#2174)
mikehaney24 Dec 10, 2018
caf84ed
Flesh out the log event and log writer classes (#2175)
mikehaney24 Dec 11, 2018
cd67dae
Enable travis for GoogleDataLogger using cocoapods-generate (#2185)
mikehaney24 Dec 14, 2018
fe53dd3
Create a log wrapper and better test GDLLogWriter (#2190)
mikehaney24 Dec 15, 2018
ea80142
Implement NSSecureCoding protocol for GDLLogEvent (#2191)
mikehaney24 Dec 18, 2018
e90eb78
Create some core infrastructure for backends (#2198)
mikehaney24 Dec 20, 2018
71de5e4
Implement -hash and -copy of GDLLogEvent, copy on log, and don't assi…
mikehaney24 Dec 21, 2018
a33e17d
Add some test helpers and structure for new classes (#2212)
mikehaney24 Dec 22, 2018
9b5742c
Implement some stubbed methods, update umbrella header, add missing t…
mikehaney24 Dec 22, 2018
bbd0d30
Implement log storage (#2215)
mikehaney24 Dec 24, 2018
dfa3887
Implement NSSecureCoding for GDLLogStorage (#2216)
mikehaney24 Dec 25, 2018
4ffae2c
merge master into googledatalogger branch (#2224)
mikehaney24 Jan 2, 2019
fd9b882
Create testing infrastructure that simplifies catching exceptions in …
mikehaney24 Jan 3, 2019
e129a30
Implement additional tests and enhance GDLLogEvent (#2231)
mikehaney24 Jan 3, 2019
78d9cad
Refactor to allow injection of fakes, and take warnings seriously (#2…
mikehaney24 Jan 4, 2019
6e95364
Move all unit tests to the Tests/Unit folder (#2234)
mikehaney24 Jan 4, 2019
e1557cf
s/GDLUploader->GDLUploadCoordinator/g and s/GDLLogBackend/GDLLogUploa…
mikehaney24 Jan 14, 2019
0fc2ff6
Implement a clock. (#2273)
mikehaney24 Jan 16, 2019
f8fb6f1
Enhance the log storage class (#2275)
mikehaney24 Jan 17, 2019
d92147a
Add test-related functionality, make GDLRegistrar thread-safe and tes…
mikehaney24 Jan 18, 2019
ddeb55f
Implement the upload coordinator (#2290)
mikehaney24 Jan 20, 2019
7e2d04c
Code cleanup (#2297)
mikehaney24 Jan 21, 2019
9b42a1c
Update podspec and factor out common test sources (#2336)
mikehaney24 Feb 5, 2019
e3616ff
Merge branch 'master' into googledatalogger
mikehaney24 Feb 5, 2019
44b7e3a
Implement an integration/E2E test of the logging pipeline (#2356)
mikehaney24 Feb 7, 2019
2c41e7d
Change cocoapods version from 1.6.0.rc.2 to 1.6.0. (#2358)
mikehaney24 Feb 7, 2019
54b7dd7
Merge remote-tracking branch 'origin/master' into mph-googledatalogger
mikehaney24 Feb 7, 2019
ce33600
Rename googledatalogger to GoogleDataTransport (#2379)
mikehaney24 Feb 11, 2019
202c290
Change travis config to googledatatransport instead of googledatalogger
mikehaney24 Feb 11, 2019
7fa0e43
Add 'upload packages' to allow prioritizers to pass arbitrary data to…
mikehaney24 Mar 5, 2019
f6dfd8e
Implement a stored event object to simplify in-memory storage (#2497)
mikehaney24 Mar 8, 2019
47413cc
Merge branch 'master' into mph-googledatatransport
mikehaney24 Mar 8, 2019
2438383
Lay the groundwork for CCT support, and include the prioritizer imple…
mikehaney24 Mar 22, 2019
a424ea8
Expose all properties of a GDTClock, better -hash and -isEqual impls …
mikehaney24 Mar 26, 2019
959e8b9
Implement the CCT proto using nanopb (#2652)
mikehaney24 Mar 29, 2019
db3da2e
Make high priority events force an upload via upload conditions (#2699)
mikehaney24 Apr 2, 2019
1f15c95
Implement the CCT prioritizer and an integration test (#2701)
mikehaney24 Apr 2, 2019
ff85a57
Change library podspecs to require 1.5.3, and change old tag string (…
mikehaney24 Apr 2, 2019
995b9dc
Remove the GULLogger dependency (#2703)
mikehaney24 Apr 2, 2019
6bc5f05
Remove the .proto and .options files from the cocoapod (#2708)
mikehaney24 Apr 2, 2019
74d65b3
Implement app-lifecycle groundwork (#2800)
mikehaney24 Apr 10, 2019
e8e88d3
Implement app lifecycle reactivity. (#2801)
mikehaney24 Apr 11, 2019
20cb973
Implement reachability and upload conditions (#2826)
mikehaney24 Apr 12, 2019
280da58
Merge branch 'master' into mph-googledatatransport
mikehaney24 Apr 12, 2019
a0c8f5b
Lower cocoapods required version to 1.4.0 and remove googledatatransp…
mikehaney24 Apr 13, 2019
010c42e
Add travis_retry for GoogleDataTransport unit tests.
mikehaney24 Apr 13, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,26 @@ jobs:
# The travis_wait is necessary because the command takes more than 10 minutes.
- travis_wait 45 ./scripts/pod_lib_lint.sh FirebaseFirestore.podspec --use-libraries --allow-warnings --no-subspecs

# GoogleDataTransport unit tests and pod linting using the default Xcode version.
- stage: test
env:
- PROJECT=GoogleDataTransport PLATFORM=iOS METHOD=xcodebuild
before_install:
- ./scripts/if_changed.sh ./scripts/install_prereqs.sh
script:
- travis_retry ./scripts/if_changed.sh ./scripts/build.sh $PROJECT $PLATFORM
- travis_retry ./scripts/if_changed.sh ./scripts/pod_lib_lint.sh GoogleDataTransport.podspec

# GoogleDataTransportCCTSupport unit tests and pod linting using the default Xcode version.
- stage: test
env:
- PROJECT=GoogleDataTransportCCTSupport PLATFORM=iOS METHOD=xcodebuild
before_install:
- ./scripts/if_changed.sh ./scripts/install_prereqs.sh
script:
- ./scripts/if_changed.sh ./scripts/build.sh $PROJECT $PLATFORM
- ./scripts/if_changed.sh ./scripts/pod_lib_lint.sh GoogleDataTransportCCTSupport.podspec

# Daily test for symbol collisions between Firebase and CocoaPods.
- stage: test
if: type = cron
Expand Down
55 changes: 55 additions & 0 deletions GoogleDataTransport.podspec
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
Pod::Spec.new do |s|
s.name = 'GoogleDataTransport'
s.version = '0.1.0'
s.summary = 'Google iOS SDK data transport.'

s.description = <<-DESC
Shared library for iOS SDK data transport needs.
DESC

s.homepage = 'https://developers.google.com/'
s.license = { :type => 'Apache', :file => 'LICENSE' }
s.authors = 'Google, Inc.'
s.source = {
:git => 'https://github.com/firebase/firebase-ios-sdk.git',
:tag => 'GoogleDataTransport-' + s.version.to_s
}

s.ios.deployment_target = '8.0'

# To develop or run the tests, >= 1.6.0 must be installed.
s.cocoapods_version = '>= 1.4.0'

s.static_framework = true
s.prefix_header_file = false

s.source_files = 'GoogleDataTransport/GoogleDataTransport/**/*'
s.public_header_files = 'GoogleDataTransport/GoogleDataTransport/Classes/Public/*.h'
s.private_header_files = 'GoogleDataTransport/GoogleDataTransport/Classes/Private/*.h'

s.pod_target_xcconfig = {
'GCC_C_LANGUAGE_STANDARD' => 'c99',
'GCC_TREAT_WARNINGS_AS_ERRORS' => 'YES',
'CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY' => 'YES'
}

common_test_sources = ['GoogleDataTransport/Tests/Common/**/*.{h,m}']

# Unit test specs
s.test_spec 'Tests-Unit' do |test_spec|
test_spec.requires_app_host = false
test_spec.source_files = ['GoogleDataTransport/Tests/Unit/**/*.{h,m}'] + common_test_sources
end

s.test_spec 'Tests-Lifecycle' do |test_spec|
test_spec.requires_app_host = false
test_spec.source_files = ['GoogleDataTransport/Tests/Lifecycle/**/*.{h,m}'] + common_test_sources
end

# Integration test specs
s.test_spec 'Tests-Integration' do |test_spec|
test_spec.requires_app_host = false
test_spec.source_files = ['GoogleDataTransport/Tests/Integration/**/*.{h,m}'] + common_test_sources
test_spec.dependency 'GCDWebServer'
end
end
Empty file.
36 changes: 36 additions & 0 deletions GoogleDataTransport/GoogleDataTransport/Classes/GDTAssert.m
Original file line number Diff line number Diff line change
@@ -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.
*/

#include "GDTAssert.h"

GDTAssertionBlock GDTAssertionBlockToRunInsteadOfNSAssert(void) {
// This class is only compiled in by unit tests, and this should fail quickly in optimized builds.
Class GDTAssertClass = NSClassFromString(@"GDTAssertHelper");
if (__builtin_expect(!!GDTAssertClass, 0)) {
SEL assertionBlockSEL = NSSelectorFromString(@"assertionBlock");
if (assertionBlockSEL) {
IMP assertionBlockIMP = [GDTAssertClass methodForSelector:assertionBlockSEL];
if (assertionBlockIMP) {
GDTAssertionBlock assertionBlock =
((GDTAssertionBlock(*)(id, SEL))assertionBlockIMP)(GDTAssertClass, assertionBlockSEL);
if (assertionBlock) {
return assertionBlock;
}
}
}
}
return NULL;
}
162 changes: 162 additions & 0 deletions GoogleDataTransport/GoogleDataTransport/Classes/GDTClock.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
/*
* 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 "GDTClock.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.
*
* Inspired by https://stackoverflow.com/a/40497811
*
* @return The KERN_BOOTTIME property from sysctl, in nanoseconds.
*/
static int64_t KernelBootTimeInNanoseconds() {
// 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_MSEC + (int64_t)boottime.tv_usec;
}

/** Returns value of gettimeofday, in nanoseconds.
*
* Inspired by https://stackoverflow.com/a/40497811
*
* @return The value of gettimeofday, in nanoseconds.
*/
static int64_t UptimeInNanoseconds() {
int64_t before_now;
int64_t after_now;
struct timeval now;

before_now = KernelBootTimeInNanoseconds();
// Addresses a race condition in which the system time has updated, but the boottime has not.
do {
gettimeofday(&now, NULL);
after_now = KernelBootTimeInNanoseconds();
} while (after_now != before_now);
return (int64_t)now.tv_sec * NSEC_PER_MSEC + (int64_t)now.tv_usec - before_now;
}

// TODO: Consider adding a 'trustedTime' property that can be populated by the response from a BE.
@implementation GDTClock

- (instancetype)init {
self = [super init];
if (self) {
_kernelBootTime = KernelBootTimeInNanoseconds();
_uptime = UptimeInNanoseconds();
_timeMillis =
(int64_t)((CFAbsoluteTimeGetCurrent() + kCFAbsoluteTimeIntervalSince1970) * NSEC_PER_USEC);
CFTimeZoneRef timeZoneRef = CFTimeZoneCopySystem();
_timezoneOffsetSeconds = CFTimeZoneGetSecondsFromGMT(timeZoneRef, 0);
CFRelease(timeZoneRef);
}
return self;
}

+ (GDTClock *)snapshot {
return [[GDTClock alloc] init];
}

+ (instancetype)clockSnapshotInTheFuture:(uint64_t)millisInTheFuture {
GDTClock *snapshot = [self snapshot];
snapshot->_timeMillis += millisInTheFuture;
return snapshot;
}

- (BOOL)isAfter:(GDTClock *)otherClock {
// These clocks are trivially comparable when they share a kernel boot time.
if (_kernelBootTime == otherClock->_kernelBootTime) {
return _uptime > otherClock->_uptime;
} else {
int64_t kernelBootTimeDiff = otherClock->_kernelBootTime - _kernelBootTime;
// 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;
}
}

- (NSUInteger)hash {
return [@(_kernelBootTime) hash] ^ [@(_uptime) 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 kGDTClockTimeMillisKey = @"GDTClockTimeMillis";

/** NSKeyedCoder key for timezoneOffsetMillis property. */
static NSString *const kGDTClockTimezoneOffsetSeconds = @"GDTClockTimezoneOffsetSeconds";

/** NSKeyedCoder key for _kernelBootTime ivar. */
static NSString *const kGDTClockKernelBootTime = @"GDTClockKernelBootTime";

/** NSKeyedCoder key for _uptime ivar. */
static NSString *const kGDTClockUptime = @"GDTClockUptime";

+ (BOOL)supportsSecureCoding {
return YES;
}

- (instancetype)initWithCoder:(NSCoder *)aDecoder {
self = [super init];
if (self) {
// TODO: If the kernelBootTime is more recent, we need to change the kernel boot time and
// uptimeMillis ivars
_timeMillis = [aDecoder decodeInt64ForKey:kGDTClockTimeMillisKey];
_timezoneOffsetSeconds = [aDecoder decodeInt64ForKey:kGDTClockTimezoneOffsetSeconds];
_kernelBootTime = [aDecoder decodeInt64ForKey:kGDTClockKernelBootTime];
_uptime = [aDecoder decodeInt64ForKey:kGDTClockUptime];
}
return self;
}

- (void)encodeWithCoder:(NSCoder *)aCoder {
[aCoder encodeInt64:_timeMillis forKey:kGDTClockTimeMillisKey];
[aCoder encodeInt64:_timezoneOffsetSeconds forKey:kGDTClockTimezoneOffsetSeconds];
[aCoder encodeInt64:_kernelBootTime forKey:kGDTClockKernelBootTime];
[aCoder encodeInt64:_uptime forKey:kGDTClockUptime];
}

@end
36 changes: 36 additions & 0 deletions GoogleDataTransport/GoogleDataTransport/Classes/GDTConsoleLogger.m
Original file line number Diff line number Diff line change
@@ -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 "GDTConsoleLogger.h"

/** The console logger prefix. */
static NSString *kGDTConsoleLogger = @"[GoogleDataTransport]";

NSString *GDTMessageCodeEnumToString(GDTMessageCode code) {
return [[NSString alloc] initWithFormat:@"I-GDT%06ld", (long)code];
}

void GDTLog(GDTMessageCode code, NSString *format, ...) {
// Don't log anything in not debug builds.
#ifndef NDEBUG
NSString *logFormat = [NSString
stringWithFormat:@"%@[%@] %@", kGDTConsoleLogger, GDTMessageCodeEnumToString(code), format];
va_list args;
va_start(args, format);
NSLogv(logFormat, args);
va_end(args);
#endif // NDEBUG
}
Loading