Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/main' into armcknight/feat/launc…
Browse files Browse the repository at this point in the history
…h-profiling
  • Loading branch information
armcknight committed Feb 2, 2024
2 parents 593fdba + 1c96132 commit 3cb46dc
Show file tree
Hide file tree
Showing 18 changed files with 280 additions and 81 deletions.
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,13 @@

## Unreleased

### Improvements

- Cache installationID async to avoid file IO on the main thread when starting the SDK (#3601)


## 8.20.0

### Features

- Add visionOS as device family (#3548)
Expand All @@ -14,6 +21,8 @@
- Clarify FramesTracker log message (#3570)
- Fix rare battery breadcrumbs crash (#3582)
- Fix synchronization issue in FramesTracker (#3571)
- Fix SentryFileManager logs warning for .DS_Files (#3584)
- Fix FileManager logs info instead of error when a path doesn't exist (#3594)

## 8.19.0

Expand Down
8 changes: 4 additions & 4 deletions Samples/iOS-Swift/iOS-Swift.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -1252,7 +1252,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 8.19.0;
MARKETING_VERSION = 8.20.0;
PRODUCT_BUNDLE_IDENTIFIER = "io.sentry.sample.iOS-Swift";
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "match Development io.sentry.sample.iOS-Swift";
Expand Down Expand Up @@ -1281,7 +1281,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 8.19.0;
MARKETING_VERSION = 8.20.0;
PRODUCT_BUNDLE_IDENTIFIER = "io.sentry.sample.iOS-Swift";
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "match AppStore io.sentry.sample.iOS-Swift";
Expand Down Expand Up @@ -1928,7 +1928,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 8.19.0;
MARKETING_VERSION = 8.20.0;
PRODUCT_BUNDLE_IDENTIFIER = "io.sentry.sample.iOS-Swift.Clip";
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "match Development io.sentry.sample.iOS-Swift.Clip";
Expand Down Expand Up @@ -1963,7 +1963,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 8.19.0;
MARKETING_VERSION = 8.20.0;
PRODUCT_BUNDLE_IDENTIFIER = "io.sentry.sample.iOS-Swift.Clip";
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "match AppStore io.sentry.sample.iOS-Swift.Clip";
Expand Down
4 changes: 2 additions & 2 deletions Sentry.podspec
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = "Sentry"
s.version = "8.19.0"
s.version = "8.20.0"
s.summary = "Sentry client for cocoa"
s.homepage = "https://github.com/getsentry/sentry-cocoa"
s.license = "mit"
Expand All @@ -27,7 +27,7 @@ Pod::Spec.new do |s|
}

s.default_subspecs = ['Core']
s.dependency "SentryPrivate", "8.19.0"
s.dependency "SentryPrivate", "8.20.0"

s.subspec 'Core' do |sp|
sp.source_files = "Sources/Sentry/**/*.{h,hpp,m,mm,c,cpp}",
Expand Down
2 changes: 1 addition & 1 deletion SentryPrivate.podspec
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = "SentryPrivate"
s.version = "8.19.0"
s.version = "8.20.0"
s.summary = "Sentry Private Library."
s.homepage = "https://github.com/getsentry/sentry-cocoa"
s.license = "mit"
Expand Down
4 changes: 2 additions & 2 deletions SentrySwiftUI.podspec
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = "SentrySwiftUI"
s.version = "8.19.0"
s.version = "8.20.0"
s.summary = "Sentry client for SwiftUI"
s.homepage = "https://github.com/getsentry/sentry-cocoa"
s.license = "mit"
Expand All @@ -19,5 +19,5 @@ Pod::Spec.new do |s|
s.watchos.framework = 'WatchKit'

s.source_files = "Sources/SentrySwiftUI/**/*.{swift,h,m}"
s.dependency 'Sentry', "8.19.0"
s.dependency 'Sentry', "8.20.0"
end
2 changes: 1 addition & 1 deletion Sources/Configuration/Sentry.xcconfig
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@ PRODUCT_NAME = Sentry
INFOPLIST_FILE = Sources/Resources/Info.plist
PRODUCT_BUNDLE_IDENTIFIER = io.sentry.Sentry

CURRENT_PROJECT_VERSION = 8.19.0
CURRENT_PROJECT_VERSION = 8.20.0

MODULEMAP_FILE = $(SRCROOT)/Sources/Resources/Sentry.modulemap
2 changes: 1 addition & 1 deletion Sources/Configuration/SentryPrivate.xcconfig
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
PRODUCT_NAME = SentryPrivate
MACH_O_TYPE = staticlib
CURRENT_PROJECT_VERSION = 8.19.0
CURRENT_PROJECT_VERSION = 8.20.0
4 changes: 4 additions & 0 deletions Sources/Sentry/SentryClient.m
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,10 @@ - (instancetype)initWithOptions:(SentryOptions *)options
self.timezone = timezone;
self.attachmentProcessors = [[NSMutableArray alloc] init];

// The SDK stores the installationID in a file. The first call requires file IO. To avoid
// executing this on the main thread, we cache the installationID async here.
[SentryInstallation cacheIDAsyncWithCacheDirectoryPath:options.cacheDirectoryPath];

if (deleteOldEnvelopeItems) {
[fileManager deleteOldEnvelopeItems];
}
Expand Down
67 changes: 47 additions & 20 deletions Sources/Sentry/SentryFileManager.m
Original file line number Diff line number Diff line change
Expand Up @@ -188,29 +188,51 @@ - (SentryFileContents *_Nullable)getFileContents:(NSString *)folderPath
- (void)deleteOldEnvelopesFromAllSentryPaths
{
// First we find all directories in the base path, these are all the various hashed DSN paths
for (NSString *path in [self allFilesInFolder:self.basePath]) {
NSString *fullPath = [self.basePath stringByAppendingPathComponent:path];
NSDictionary *dict = [[NSFileManager defaultManager] attributesOfItemAtPath:fullPath
error:nil];
if (!dict || dict[NSFileType] != NSFileTypeDirectory) {
SENTRY_LOG_WARN(@"Could not get NSFileTypeDirectory from %@", fullPath);
continue;
}

// If the options don't have a DSN the sentry path doesn't contain a hash and the envelopes
// folder is stored in the base path.
NSString *envelopesPath;
if ([fullPath hasSuffix:EnvelopesPathComponent]) {
envelopesPath = fullPath;
} else {
envelopesPath = [fullPath stringByAppendingPathComponent:EnvelopesPathComponent];
}
for (NSString *filePath in [self allFilesInFolder:self.basePath]) {
NSString *envelopesPath = [self getEnvelopesPath:filePath];

// Then we will remove all old items from the envelopes subdirectory
[self deleteOldEnvelopesFromPath:envelopesPath];
}
}

- (nullable NSString *)getEnvelopesPath:(NSString *)filePath
{
NSString *fullPath = [self.basePath stringByAppendingPathComponent:filePath];

if ([fullPath hasSuffix:@".DS_Store"]) {
SENTRY_LOG_DEBUG(
@"Ignoring .DS_Store file when building envelopes path at path: %@", fullPath);
return nil;
}

NSError *error = nil;
NSDictionary *dict = [[NSFileManager defaultManager] attributesOfItemAtPath:fullPath
error:&error];
if (error != nil) {
SENTRY_LOG_WARN(
@"Could not get attributes of item at path: %@. Error: %@", fullPath, error);
return nil;
}

if (dict[NSFileType] != NSFileTypeDirectory) {
SENTRY_LOG_DEBUG(
@"Ignoring non directory when deleting old envelopes at path: %@", fullPath);
return nil;
}

// If the options don't have a DSN the sentry path doesn't contain a hash and the envelopes
// folder is stored in the base path.
NSString *envelopesPath;
if ([fullPath hasSuffix:EnvelopesPathComponent]) {
envelopesPath = fullPath;
} else {
envelopesPath = [fullPath stringByAppendingPathComponent:EnvelopesPathComponent];
}

return envelopesPath;
}

- (void)deleteOldEnvelopesFromPath:(NSString *)envelopesPath
{
NSTimeInterval now =
Expand Down Expand Up @@ -246,11 +268,16 @@ - (void)deleteAllEnvelopes
- (NSArray<NSString *> *)allFilesInFolder:(NSString *)path
{
NSFileManager *fileManager = [NSFileManager defaultManager];
if (![fileManager fileExistsAtPath:path]) {
SENTRY_LOG_INFO(@"Returning empty files list, as folder doesn't exist at path: %@", path);
return @[];
}

NSError *error = nil;
NSArray<NSString *> *storedFiles = [fileManager contentsOfDirectoryAtPath:path error:&error];
if (nil != error) {
if (error != nil) {
SENTRY_LOG_ERROR(@"Couldn't load files in folder %@: %@", path, error);
return [NSArray new];
return @[];
}
return [storedFiles sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)];
}
Expand Down Expand Up @@ -660,7 +687,7 @@ + (BOOL)createDirectoryAtPath:(NSString *)path withError:(NSError **)error

#pragma mark private methods

- (void)createPathsWithOptions:(SentryOptions *_Nonnull)options
- (void)createPathsWithOptions:(SentryOptions *)options
{
NSString *cachePath = options.cacheDirectoryPath;

Expand Down
42 changes: 35 additions & 7 deletions Sources/Sentry/SentryInstallation.m
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#import "SentryInstallation.h"
#import "SentryDefines.h"
#import "SentryDependencyContainer.h"
#import "SentryDispatchQueueWrapper.h"
#import "SentryLog.h"

NS_ASSUME_NONNULL_BEGIN
Expand All @@ -8,6 +10,7 @@
SentryInstallation ()
@property (class, nonatomic, readonly)
NSMutableDictionary<NSString *, NSString *> *installationStringsByCacheDirectoryPaths;

@end

@implementation SentryInstallation
Expand All @@ -31,32 +34,57 @@ + (NSString *)idWithCacheDirectoryPath:(NSString *)cacheDirectoryPath
return installationString;
}

NSString *cachePath = cacheDirectoryPath;
NSString *installationFilePath = [cachePath stringByAppendingPathComponent:@"INSTALLATION"];
NSData *installationData = [NSData dataWithContentsOfFile:installationFilePath];
installationString =
[SentryInstallation idWithCacheDirectoryPathNonCached:cacheDirectoryPath];

if (nil == installationData) {
if (installationString == nil) {
installationString = [NSUUID UUID].UUIDString;

NSData *installationStringData =
[installationString dataUsingEncoding:NSUTF8StringEncoding];
NSFileManager *fileManager = [NSFileManager defaultManager];

NSString *installationFilePath =
[SentryInstallation installationFilePath:cacheDirectoryPath];

if (![fileManager createFileAtPath:installationFilePath
contents:installationStringData
attributes:nil]) {
SENTRY_LOG_ERROR(
@"Failed to store installationID file at path %@", installationFilePath);
}
} else {
installationString = [[NSString alloc] initWithData:installationData
encoding:NSUTF8StringEncoding];
}

self.installationStringsByCacheDirectoryPaths[cacheDirectoryPath] = installationString;
return installationString;
}
}

+ (nullable NSString *)idWithCacheDirectoryPathNonCached:(NSString *)cacheDirectoryPath
{
NSString *installationFilePath = [SentryInstallation installationFilePath:cacheDirectoryPath];

NSData *installationData = [NSData dataWithContentsOfFile:installationFilePath];

if (installationData != nil) {
return [[NSString alloc] initWithData:installationData encoding:NSUTF8StringEncoding];
} else {
return nil;
}
}

+ (void)cacheIDAsyncWithCacheDirectoryPath:(NSString *)cacheDirectoryPath
{
[SentryDependencyContainer.sharedInstance.dispatchQueueWrapper dispatchAsyncWithBlock:^{
[SentryInstallation idWithCacheDirectoryPath:cacheDirectoryPath];
}];
}

+ (NSString *)installationFilePath:(NSString *)cacheDirectoryPath
{
return [cacheDirectoryPath stringByAppendingPathComponent:@"INSTALLATION"];
}

@end

NS_ASSUME_NONNULL_END
2 changes: 1 addition & 1 deletion Sources/Sentry/SentryMeta.m
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ @implementation SentryMeta
// Don't remove the static keyword. If you do the compiler adds the constant name to the global
// symbol table and it might clash with other constants. When keeping the static keyword the
// compiler replaces all occurrences with the value.
static NSString *versionString = @"8.19.0";
static NSString *versionString = @"8.20.0";
static NSString *sdkName = @"sentry.cocoa";

+ (NSString *)versionString
Expand Down
9 changes: 6 additions & 3 deletions Sources/Sentry/include/SentryFileManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ NS_ASSUME_NONNULL_BEGIN
@class SentryOptions;
@class SentrySession;

NS_SWIFT_NAME(SentryFileManager)
@interface SentryFileManager : NSObject
SENTRY_NO_INIT

@property (nonatomic, readonly) NSString *basePath;
@property (nonatomic, readonly) NSString *sentryPath;
@property (nonatomic, readonly) NSString *breadcrumbsFilePathOne;
@property (nonatomic, readonly) NSString *breadcrumbsFilePathTwo;
Expand Down Expand Up @@ -56,6 +56,11 @@ SENTRY_NO_INIT

- (void)deleteOldEnvelopeItems;

/**
* Only used for testing.
*/
- (nullable NSString *)getEnvelopesPath:(NSString *)filePath;

/**
* Get all envelopes sorted ascending by the @c timeIntervalSince1970 the envelope was stored and if
* two envelopes are stored at the same time sorted by the order they were stored.
Expand All @@ -70,8 +75,6 @@ SENTRY_NO_INIT

- (void)removeFileAtPath:(NSString *)path;

- (NSArray<NSString *> *)allFilesInFolder:(NSString *)path;

- (void)storeAppState:(SentryAppState *)appState;
- (void)moveAppStateToPreviousAppState;
- (SentryAppState *_Nullable)readAppState;
Expand Down
4 changes: 4 additions & 0 deletions Sources/Sentry/include/SentryInstallation.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ NS_ASSUME_NONNULL_BEGIN

+ (NSString *)idWithCacheDirectoryPath:(NSString *)cacheDirectoryPath;

+ (nullable NSString *)idWithCacheDirectoryPathNonCached:(NSString *)cacheDirectoryPath;

+ (void)cacheIDAsyncWithCacheDirectoryPath:(NSString *)cacheDirectoryPath;

@end

NS_ASSUME_NONNULL_END
2 changes: 1 addition & 1 deletion Tests/HybridSDKTest/HybridPod.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,6 @@ Pod::Spec.new do |s|
s.requires_arc = true
s.frameworks = 'Foundation'
s.swift_versions = "5.5"
s.dependency "Sentry/HybridSDK", "8.19.0"
s.dependency "Sentry/HybridSDK", "8.20.0"
s.source_files = "HybridTest.swift"
end
Loading

0 comments on commit 3cb46dc

Please sign in to comment.