Skip to content

Commit

Permalink
[Rollouts] Feature rollouts merge to main (#12410)
Browse files Browse the repository at this point in the history
  • Loading branch information
themiswang authored Mar 11, 2024
1 parent 07b7669 commit 90c33e4
Show file tree
Hide file tree
Showing 73 changed files with 3,281 additions and 177 deletions.
1 change: 1 addition & 0 deletions CoreOnly/Tests/FirebasePodTest/Podfile
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ target 'FirebasePodTest' do
pod 'FirebaseAppCheckInterop', :path => '../../../'
pod 'FirebaseAuthInterop', :path => '../../../'
pod 'FirebaseMessagingInterop', :path => '../../../'
pod 'FirebaseRemoteConfigInterop', :path => '../../../'
pod 'FirebaseCoreInternal', :path => '../../../'
pod 'FirebaseCoreExtension', :path => '../../../'
pod 'FirebaseSessions', :path => '../../../'
Expand Down
1 change: 1 addition & 0 deletions Crashlytics/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# Unreleased
- [added] Updated upload-symbols to 13.7 with VisionPro build phase support. (#12306)
- [changed] Added support for Crashlytics to report metadata about Remote Config keys and values.

# 10.22.0
- [fixed] Force validation or rotation of FIDs for FirebaseSessions.
Expand Down
4 changes: 3 additions & 1 deletion Crashlytics/Crashlytics/Components/FIRCLSUserLogging.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,9 @@ void FIRCLSUserLoggingRecordUserKeysAndValues(NSDictionary* keysAndValues);
void FIRCLSUserLoggingRecordInternalKeyValue(NSString* key, id value);
void FIRCLSUserLoggingWriteInternalKeyValue(NSString* key, NSString* value);

void FIRCLSUserLoggingRecordError(NSError* error, NSDictionary<NSString*, id>* additionalUserInfo);
void FIRCLSUserLoggingRecordError(NSError* error,
NSDictionary<NSString*, id>* additionalUserInfo,
NSString* rolloutsInfoJSON);

NSDictionary* FIRCLSUserLoggingGetCompactedKVEntries(FIRCLSUserLoggingKVStorage* storage,
bool decodeHex);
Expand Down
16 changes: 13 additions & 3 deletions Crashlytics/Crashlytics/Components/FIRCLSUserLogging.m
Original file line number Diff line number Diff line change
Expand Up @@ -355,7 +355,8 @@ static void FIRCLSUserLoggingWriteError(FIRCLSFile *file,
NSError *error,
NSDictionary<NSString *, id> *additionalUserInfo,
NSArray *addresses,
uint64_t timestamp) {
uint64_t timestamp,
NSString *rolloutsInfoJSON) {
FIRCLSFileWriteSectionStart(file, "error");
FIRCLSFileWriteHashStart(file);
FIRCLSFileWriteHashEntryHexEncodedString(file, "domain", [[error domain] UTF8String]);
Expand All @@ -374,12 +375,20 @@ static void FIRCLSUserLoggingWriteError(FIRCLSFile *file,
FIRCLSUserLoggingRecordErrorUserInfo(file, "info", [error userInfo]);
FIRCLSUserLoggingRecordErrorUserInfo(file, "extra_info", additionalUserInfo);

// rollouts
if (rolloutsInfoJSON) {
FIRCLSFileWriteHashKey(file, "rollouts");
FIRCLSFileWriteStringUnquoted(file, [rolloutsInfoJSON UTF8String]);
FIRCLSFileWriteHashEnd(file);
}

FIRCLSFileWriteHashEnd(file);
FIRCLSFileWriteSectionEnd(file);
}

void FIRCLSUserLoggingRecordError(NSError *error,
NSDictionary<NSString *, id> *additionalUserInfo) {
NSDictionary<NSString *, id> *additionalUserInfo,
NSString *rolloutsInfoJSON) {
if (!error) {
return;
}
Expand All @@ -396,7 +405,8 @@ void FIRCLSUserLoggingRecordError(NSError *error,
FIRCLSUserLoggingWriteAndCheckABFiles(
&_firclsContext.readonly->logging.errorStorage,
&_firclsContext.writable->logging.activeErrorLogPath, ^(FIRCLSFile *file) {
FIRCLSUserLoggingWriteError(file, error, additionalUserInfo, addresses, timestamp);
FIRCLSUserLoggingWriteError(file, error, additionalUserInfo, addresses, timestamp,
rolloutsInfoJSON);
});
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// 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.

#if SWIFT_PACKAGE
@import FirebaseCrashlyticsSwift;
#else // Swift Package Manager
#import <FirebaseCrashlytics/FirebaseCrashlytics-Swift.h>
#endif // CocoaPods

@interface FIRCLSRolloutsPersistenceManager : NSObject <FIRCLSPersistenceLog>

- (instancetype _Nullable)initWithFileManager:(FIRCLSFileManager *_Nonnull)fileManager;
- (instancetype _Nonnull)init NS_UNAVAILABLE;
+ (instancetype _Nonnull)new NS_UNAVAILABLE;

- (void)updateRolloutsStateToPersistenceWithRollouts:(NSData *_Nonnull)rollouts
reportID:(NSString *_Nonnull)reportID;
- (void)debugLogWithMessage:(NSString *_Nonnull)message;
@end
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
// 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>
#include "Crashlytics/Crashlytics/Components/FIRCLSGlobals.h"
#include "Crashlytics/Crashlytics/Components/FIRCLSUserLogging.h"
#import "Crashlytics/Crashlytics/Helpers/FIRCLSLogger.h"
#import "Crashlytics/Crashlytics/Models/FIRCLSFileManager.h"
#import "Crashlytics/Crashlytics/Models/FIRCLSInternalReport.h"

#if SWIFT_PACKAGE
@import FirebaseCrashlyticsSwift;
#else // Swift Package Manager
#import <FirebaseCrashlytics/FirebaseCrashlytics-Swift.h>
#endif // CocoaPods

@interface FIRCLSRolloutsPersistenceManager : NSObject <FIRCLSPersistenceLog>
@property(nonatomic, readonly) FIRCLSFileManager *fileManager;
@end

@implementation FIRCLSRolloutsPersistenceManager
- (instancetype)initWithFileManager:(FIRCLSFileManager *)fileManager {
self = [super init];
if (!self) {
return nil;
}
_fileManager = fileManager;
return self;
}

- (void)updateRolloutsStateToPersistenceWithRollouts:(NSData *_Nonnull)rollouts
reportID:(NSString *_Nonnull)reportID {
NSString *rolloutsPath = [[[_fileManager activePath] stringByAppendingPathComponent:reportID]
stringByAppendingPathComponent:FIRCLSReportRolloutsFile];
if (![_fileManager fileExistsAtPath:rolloutsPath]) {
if (![_fileManager createFileAtPath:rolloutsPath contents:nil attributes:nil]) {
FIRCLSDebugLog(@"Could not create rollouts.clsrecord file. Error was code: %d - message: %s",
errno, strerror(errno));
}
}

NSFileHandle *rolloutsFile = [NSFileHandle fileHandleForUpdatingAtPath:rolloutsPath];

dispatch_sync(FIRCLSGetLoggingQueue(), ^{
[rolloutsFile seekToEndOfFile];
[rolloutsFile writeData:rollouts];
NSData *newLineData = [@"\n" dataUsingEncoding:NSUTF8StringEncoding];
[rolloutsFile writeData:newLineData];
});
}

- (void)debugLogWithMessage:(NSString *_Nonnull)message {
FIRCLSDebugLog(message);
}

@end
51 changes: 45 additions & 6 deletions Crashlytics/Crashlytics/FIRCrashlytics.m
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#import "Crashlytics/Crashlytics/Helpers/FIRCLSDefines.h"
#include "Crashlytics/Crashlytics/Helpers/FIRCLSProfiling.h"
#include "Crashlytics/Crashlytics/Helpers/FIRCLSUtility.h"
#import "Crashlytics/Crashlytics/Models/FIRCLSExecutionIdentifierModel.h"
#import "Crashlytics/Crashlytics/Models/FIRCLSFileManager.h"
#import "Crashlytics/Crashlytics/Models/FIRCLSSettings.h"
#import "Crashlytics/Crashlytics/Settings/Models/FIRCLSApplicationIdentifierModel.h"
Expand All @@ -47,6 +48,7 @@
#import "Crashlytics/Crashlytics/Controllers/FIRCLSNotificationManager.h"
#import "Crashlytics/Crashlytics/Controllers/FIRCLSReportManager.h"
#import "Crashlytics/Crashlytics/Controllers/FIRCLSReportUploader.h"
#import "Crashlytics/Crashlytics/Controllers/FIRCLSRolloutsPersistenceManager.h"
#import "Crashlytics/Crashlytics/Private/FIRCLSExistingReportManager_Private.h"
#import "Crashlytics/Crashlytics/Private/FIRCLSOnDemandModel_Private.h"
#import "Crashlytics/Crashlytics/Private/FIRExceptionModel_Private.h"
Expand All @@ -58,6 +60,12 @@
#import <GoogleDataTransport/GoogleDataTransport.h>

@import FirebaseSessions;
@import FirebaseRemoteConfigInterop;
#if SWIFT_PACKAGE
@import FirebaseCrashlyticsSwift;
#else // Swift Package Manager
#import <FirebaseCrashlytics/FirebaseCrashlytics-Swift.h>
#endif // CocoaPods

#if TARGET_OS_IPHONE
#import <UIKit/UIKit.h>
Expand All @@ -76,7 +84,10 @@
@protocol FIRCrashlyticsInstanceProvider <NSObject>
@end

@interface FIRCrashlytics () <FIRLibrary, FIRCrashlyticsInstanceProvider, FIRSessionsSubscriber>
@interface FIRCrashlytics () <FIRLibrary,
FIRCrashlyticsInstanceProvider,
FIRSessionsSubscriber,
FIRRolloutsStateSubscriber>

@property(nonatomic) BOOL didPreviouslyCrash;
@property(nonatomic, copy) NSString *googleAppID;
Expand All @@ -91,6 +102,8 @@ @interface FIRCrashlytics () <FIRLibrary, FIRCrashlyticsInstanceProvider, FIRSes

@property(nonatomic, strong) FIRCLSAnalyticsManager *analyticsManager;

@property(nonatomic, strong) FIRCLSRemoteConfigManager *remoteConfigManager;

// Dependencies common to each of the Controllers
@property(nonatomic, strong) FIRCLSManagerData *managerData;

Expand All @@ -104,7 +117,8 @@ - (instancetype)initWithApp:(FIRApp *)app
appInfo:(NSDictionary *)appInfo
installations:(FIRInstallations *)installations
analytics:(id<FIRAnalyticsInterop>)analytics
sessions:(id<FIRSessionsProvider>)sessions {
sessions:(id<FIRSessionsProvider>)sessions
remoteConfig:(id<FIRRemoteConfigInterop>)remoteConfig {
self = [super init];

if (self) {
Expand Down Expand Up @@ -189,8 +203,19 @@ - (instancetype)initWithApp:(FIRApp *)app
}] catch:^void(NSError *error) {
FIRCLSErrorLog(@"Crash reporting failed to initialize with error: %@", error);
}];
}

// RemoteConfig subscription should be made after session report directory created.
if (remoteConfig) {
FIRCLSDebugLog(@"Registering RemoteConfig SDK subscription for rollouts data");

FIRCLSRolloutsPersistenceManager *persistenceManager =
[[FIRCLSRolloutsPersistenceManager alloc] initWithFileManager:_fileManager];
_remoteConfigManager =
[[FIRCLSRemoteConfigManager alloc] initWithRemoteConfig:remoteConfig
persistenceDelegate:persistenceManager];
[remoteConfig registerRolloutsStateSubscriber:self for:FIRRemoteConfigConstants.FIRNamespaceGoogleMobilePlatform];
}
}
return self;
}

Expand All @@ -215,6 +240,7 @@ + (void)load {

id<FIRAnalyticsInterop> analytics = FIR_COMPONENT(FIRAnalyticsInterop, container);
id<FIRSessionsProvider> sessions = FIR_COMPONENT(FIRSessionsProvider, container);
id<FIRRemoteConfigInterop> remoteConfig = FIR_COMPONENT(FIRRemoteConfigInterop, container);

FIRInstallations *installations = [FIRInstallations installationsWithApp:container.app];

Expand All @@ -224,7 +250,8 @@ + (void)load {
appInfo:NSBundle.mainBundle.infoDictionary
installations:installations
analytics:analytics
sessions:sessions];
sessions:sessions
remoteConfig:remoteConfig];
};

FIRComponent *component =
Expand Down Expand Up @@ -377,11 +404,13 @@ - (void)recordError:(NSError *)error {
}

- (void)recordError:(NSError *)error userInfo:(NSDictionary<NSString *, id> *)userInfo {
FIRCLSUserLoggingRecordError(error, userInfo);
NSString *rolloutsInfoJSON = [_remoteConfigManager getRolloutAssignmentsEncodedJsonString];
FIRCLSUserLoggingRecordError(error, userInfo, rolloutsInfoJSON);
}

- (void)recordExceptionModel:(FIRExceptionModel *)exceptionModel {
FIRCLSExceptionRecordModel(exceptionModel);
NSString *rolloutsInfoJSON = [_remoteConfigManager getRolloutAssignmentsEncodedJsonString];
FIRCLSExceptionRecordModel(exceptionModel, rolloutsInfoJSON);
}

- (void)recordOnDemandExceptionModel:(FIRExceptionModel *)exceptionModel {
Expand All @@ -407,4 +436,14 @@ - (FIRSessionsSubscriberName)sessionsSubscriberName {
return FIRSessionsSubscriberNameCrashlytics;
}

#pragma mark - FIRRolloutsStateSubscriber
- (void)rolloutsStateDidChange:(FIRRolloutsState *_Nonnull)rolloutsState {
if (!_remoteConfigManager) {
FIRCLSDebugLog(@"rolloutsStateDidChange gets called without init the rc manager.");
return;
}
NSString *currentReportID = _managerData.executionIDModel.executionID;
[_remoteConfigManager updateRolloutsStateWithRolloutsState:rolloutsState
reportID:currentReportID];
}
@end
5 changes: 3 additions & 2 deletions Crashlytics/Crashlytics/Handlers/FIRCLSException.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,15 +60,16 @@ void FIRCLSExceptionRaiseTestObjCException(void) __attribute((noreturn));
void FIRCLSExceptionRaiseTestCppException(void) __attribute((noreturn));

#ifdef __OBJC__
void FIRCLSExceptionRecordModel(FIRExceptionModel* exceptionModel);
void FIRCLSExceptionRecordModel(FIRExceptionModel* exceptionModel, NSString* rolloutsInfoJSON);
NSString* FIRCLSExceptionRecordOnDemandModel(FIRExceptionModel* exceptionModel,
int previousRecordedOnDemandExceptions,
int previousDroppedOnDemandExceptions);
void FIRCLSExceptionRecordNSException(NSException* exception);
void FIRCLSExceptionRecord(FIRCLSExceptionType type,
const char* name,
const char* reason,
NSArray<FIRStackFrame*>* frames);
NSArray<FIRStackFrame*>* frames,
NSString* rolloutsInfoJSON);
NSString* FIRCLSExceptionRecordOnDemand(FIRCLSExceptionType type,
const char* name,
const char* reason,
Expand Down
Loading

0 comments on commit 90c33e4

Please sign in to comment.