diff --git a/Configuration/Realm/Realm iOS static.xcconfig b/Configuration/Realm/Realm iOS static.xcconfig index 25c48d7c2e..ebc5f6aa6f 100644 --- a/Configuration/Realm/Realm iOS static.xcconfig +++ b/Configuration/Realm/Realm iOS static.xcconfig @@ -11,3 +11,5 @@ CONFIGURATION_BUILD_DIR = $(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME CONFIGURATION_TEMP_DIR = $(PROJECT_TEMP_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)-static; GCC_PREPROCESSOR_DEFINITIONS = REALM_IOS_STATIC $(inherited); + +OTHER_LDFLAGS[sdk=iphone*] = $(inherited) -framework UIKit diff --git a/Configuration/Realm/Realm.xcconfig b/Configuration/Realm/Realm.xcconfig index a7a334af8e..623bf9b28c 100644 --- a/Configuration/Realm/Realm.xcconfig +++ b/Configuration/Realm/Realm.xcconfig @@ -24,3 +24,11 @@ LD_RUNPATH_SEARCH_PATHS[sdk=watch*] = $(inherited) @executable_path/Frameworks @ LD_RUNPATH_SEARCH_PATHS[sdk=appletv*] = $(inherited) @executable_path/Frameworks @loader_path/Frameworks; REALM_IOPLATFORMUUID = ""; + +OTHER_LDFLAGS[sdk=iphone*] = $(inherited) -framework UIKit +OTHER_LDFLAGS[sdk=watch*] = $(inherited) -framework UIKit +OTHER_LDFLAGS[sdk=appletv*] = $(inherited) -framework UIKit + +LINKER_FLAG_MACCATALYST_YES = $(inherited) -framework UIKit +LINKER_FLAG_MACCATALYST_NO = "" +OTHER_LDFLAGS[sdk=macosx*] = $(LINKER_FLAG_MACCATALYST_$(IS_MACCATALYST)) diff --git a/Realm.podspec b/Realm.podspec index f0acd79b4d..38e6925884 100644 --- a/Realm.podspec +++ b/Realm.podspec @@ -113,7 +113,10 @@ Pod::Spec.new do |s| 'include/RLMUpdateResult_Private.h', 'include/RLMUser_Private.h', - s.frameworks = 'Security' + s.ios.frameworks = 'Security' + s.ios.weak_framework = 'UIKit' + s.tvos.weak_framework = 'UIKit' + s.watchos.weak_framework = 'UIKit' s.module_map = 'Realm/Realm.modulemap' s.compiler_flags = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"#{s.version}\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC" s.prepare_command = 'sh scripts/setup-cocoapods.sh' diff --git a/Realm/RLMAnalytics.hpp b/Realm/RLMAnalytics.hpp index 91d412289a..76988ae44d 100644 --- a/Realm/RLMAnalytics.hpp +++ b/Realm/RLMAnalytics.hpp @@ -55,5 +55,7 @@ // - Some info about the features been used when opening the realm for the first time. #import +#import void RLMSendAnalytics(RLMRealmConfiguration *configuration, RLMSchema *schema); +NSString *RLMHashBase16Data(const void *bytes, size_t length); diff --git a/Realm/RLMAnalytics.mm b/Realm/RLMAnalytics.mm index e85d3a4985..ed9c968c27 100644 --- a/Realm/RLMAnalytics.mm +++ b/Realm/RLMAnalytics.mm @@ -126,7 +126,7 @@ static auto RLMSysCtl(int *mib, u_int mibSize, size_t *bufferSize) { } // Hash the data in the given buffer and convert it to a hex-format string -static NSString *RLMHashBase16Data(const void *bytes, size_t length) { +NSString *RLMHashBase16Data(const void *bytes, size_t length) { unsigned char buffer[CC_SHA256_DIGEST_LENGTH]; CC_SHA256(bytes, static_cast(length), buffer); diff --git a/Realm/RLMApp.mm b/Realm/RLMApp.mm index 83454116da..54a33ea849 100644 --- a/Realm/RLMApp.mm +++ b/Realm/RLMApp.mm @@ -18,6 +18,13 @@ #import "RLMApp_Private.hpp" +#import +#if __has_include() +#import +#define REALM_UIDEVICE_AVAILABLE +#endif + +#import "RLMAnalytics.hpp" #import "RLMBSON_Private.hpp" #import "RLMCredentials_Private.hpp" #import "RLMEmailPasswordAuth.h" @@ -128,21 +135,35 @@ - (instancetype)initWithBaseURL:(nullable NSString *)baseURL self.localAppName = localAppName; self.localAppVersion = localAppVersion; self.defaultRequestTimeoutMS = defaultRequestTimeoutMS; - - _config.device_info.sdk = "Realm Swift"; - - // Platform info isn't available when running via `swift test`. - // Non-Xcode SPM builds can't build for anything but macOS, so this is - // probably unimportant for now and we can just report "unknown" - auto processInfo = [NSProcessInfo processInfo]; - RLMNSStringToStdString(_config.device_info.platform_version, - [processInfo operatingSystemVersionString] ?: @"unknown"); - RLMNSStringToStdString(_config.device_info.sdk_version, REALM_COCOA_VERSION); + RLMConfigureSyncConnectionParameters(_config); return self; } return nil; } +static void RLMConfigureSyncConnectionParameters(realm::app::App::Config& config) { + // Anonymized BundleId + NSString *bundleId = [[NSBundle mainBundle] bundleIdentifier]; + NSData *bundleIdData = [bundleId dataUsingEncoding:NSUTF8StringEncoding]; + RLMNSStringToStdString(config.device_info.bundle_id, RLMHashBase16Data(bundleIdData.bytes, bundleIdData.length)); + + config.device_info.sdk = "Realm Swift"; + RLMNSStringToStdString(config.device_info.sdk_version, REALM_COCOA_VERSION); + + auto processInfo = [NSProcessInfo processInfo]; + RLMNSStringToStdString(config.device_info.platform_version, + [processInfo operatingSystemVersionString] ?: @"unknown"); + + RLMNSStringToStdString(config.device_info.framework_version, @__clang_version__); + +#ifdef REALM_UIDEVICE_AVAILABLE + RLMNSStringToStdString(config.device_info.device_name, [UIDevice currentDevice].model); +#endif + struct utsname systemInfo; + uname(&systemInfo); + config.device_info.device_version = systemInfo.machine; +} + - (realm::app::App::Config&)config { return _config; } diff --git a/Realm/Tests/RealmTests.mm b/Realm/Tests/RealmTests.mm index 91fd596c74..1bb3a9b01f 100644 --- a/Realm/Tests/RealmTests.mm +++ b/Realm/Tests/RealmTests.mm @@ -35,6 +35,10 @@ #import #import +#if !defined(REALM_COCOA_VERSION) +#import "RLMVersion.h" +#endif + @interface RLMObjectSchema (Private) + (instancetype)schemaForObjectClass:(Class)objectClass; @@ -2952,10 +2956,9 @@ - (void)tearDown { RLMLogger.defaultLogger = _logger; } - (void)testSetDefaultLogLevel { - __block NSString *logs = @""; + __block NSMutableString *logs = [[NSMutableString alloc] init]; RLMLogger *logger = [[RLMLogger alloc] initWithLevel:RLMLogLevelAll logFunction:^(RLMLogLevel level, NSString *message) { - NSString *newLogs = [logs stringByAppendingFormat:@" %@ %lu %@", [NSDate date], level, message]; - logs = newLogs; + [logs appendFormat:@" %@ %lu %@", [NSDate date], level, message]; }]; RLMLogger.defaultLogger = logger; @@ -2964,7 +2967,7 @@ - (void)testSetDefaultLogLevel { XCTAssertTrue([logs containsString:@"5 DB:"]); // Detail XCTAssertTrue([logs containsString:@"7 DB:"]); // Trace - logs = @""; + [logs setString: @""]; logger.level = RLMLogLevelDetail; @autoreleasepool { [RLMRealm defaultRealm]; } XCTAssertEqual([RLMLogger defaultLogger].level, RLMLogLevelDetail); @@ -2973,11 +2976,10 @@ - (void)testSetDefaultLogLevel { } - (void)testDefaultLogger { - __block NSString *logs = @""; + __block NSMutableString *logs = [[NSMutableString alloc] init]; RLMLogger *logger = [[RLMLogger alloc] initWithLevel:RLMLogLevelOff logFunction:^(RLMLogLevel level, NSString *message) { - NSString *newLogs = [logs stringByAppendingFormat:@" %@ %lu %@", [NSDate date], level, message]; - logs = newLogs; + [logs appendFormat:@" %@ %lu %@", [NSDate date], level, message]; }]; RLMLogger.defaultLogger = logger; XCTAssertEqual(RLMLogger.defaultLogger.level, RLMLogLevelOff); @@ -2988,23 +2990,22 @@ - (void)testDefaultLogger { // Test LogLevel Detail logger.level = RLMLogLevelDetail; @autoreleasepool { [RLMRealm defaultRealm]; } - XCTAssertTrue([logs length] >= 0); + XCTAssertTrue([logs length] > 0); XCTAssertTrue([logs containsString:@"5 DB:"]); // Detail XCTAssertFalse([logs containsString:@"7 DB:"]); // Trace // Test LogLevel All logger.level = RLMLogLevelAll; @autoreleasepool { [RLMRealm defaultRealm]; } - XCTAssertTrue([logs length] >= 0); + XCTAssertTrue([logs length] > 0); XCTAssertTrue([logs containsString:@"5 DB:"]); // Detail XCTAssertTrue([logs containsString:@"7 DB:"]); // Trace - logs = @""; + [logs setString: @""]; // Init Custom Logger RLMLogger.defaultLogger = [[RLMLogger alloc] initWithLevel:RLMLogLevelDebug logFunction:^(RLMLogLevel level, NSString * message) { - NSString *newLogs = [logs stringByAppendingFormat:@" %@ %lu %@", [NSDate date], level, message]; - logs = newLogs; + [logs appendFormat:@" %@ %lu %@", [NSDate date], level, message]; }]; XCTAssertEqual(RLMLogger.defaultLogger.level, RLMLogLevelDebug); @@ -3014,21 +3015,50 @@ - (void)testDefaultLogger { } - (void)testCustomLoggerLogMessage { - __block NSString *logs = @""; + __block NSMutableString *logs = [[NSMutableString alloc] init]; RLMLogger *logger = [[RLMLogger alloc] initWithLevel:RLMLogLevelInfo logFunction:^(RLMLogLevel level, NSString * message) { - NSString *newLogs = [logs stringByAppendingFormat:@" %@ %lu %@", [NSDate date], level, message]; - logs = newLogs; - + [logs appendFormat:@" %@ %lu %@.", [NSDate date], level, message]; }]; RLMLogger.defaultLogger = logger; - @autoreleasepool { [RLMRealm defaultRealm]; } - XCTAssertTrue([logs length] >= 0); - [logger logWithLevel:RLMLogLevelInfo message:@"%@ IMPORTANT INFO %i", @"TEST:", 0]; [logger logWithLevel:RLMLogLevelTrace message:@"IMPORTANT TRACE"]; XCTAssertTrue([logs containsString:@"TEST: IMPORTANT INFO 0"]); // Detail XCTAssertFalse([logs containsString:@"IMPORTANT TRACE"]); // Trace } @end + +@interface RLMMetricsTests : RLMTestCase +@property (nonatomic, strong) RLMLogger *logger; +@end + +@implementation RLMMetricsTests +- (void)setUp { + _logger = RLMLogger.defaultLogger; +} +- (void)tearDown { + RLMLogger.defaultLogger = _logger; +} + +- (void)testSyncConnectionMetrics { + __block NSMutableString *logs = [[NSMutableString alloc] init]; + RLMLogger *logger = [[RLMLogger alloc] initWithLevel:RLMLogLevelDebug + logFunction:^(RLMLogLevel level, NSString * message) { + [logs appendFormat:@" %@ %lu %@.", [NSDate date], level, message]; + }]; + RLMLogger.defaultLogger = logger; + RLMApp *app = [RLMApp appWithId:@"test-id"]; + // We don't even need the login to succeed, we only want for the logger + // to log the values on device info after trying to login. + [app loginWithCredential:[RLMCredentials anonymousCredentials] completion:^(RLMUser * _Nullable, NSError * _Nullable) {}]; + // Verifying that this values are set on device_info. + // Only the following values are logged by core (sdk, sdk version, platform version). + NSString *realmVersion = [NSString stringWithFormat:@"sdk version: %@", REALM_COCOA_VERSION]; + XCTAssertTrue([logs containsString: realmVersion]); + XCTAssertTrue([logs containsString:@"sdk: Realm Swift"]); + auto processInfo = [NSProcessInfo processInfo]; + NSString *version = [NSString stringWithFormat:@"version: %@",[processInfo operatingSystemVersionString]]; + XCTAssertTrue([logs containsString: version]); +} +@end