Skip to content

Commit 63c646b

Browse files
Merge pull request #250 from Countly/rc-experiment-info
Implemented remote config experiment info calls
2 parents 8a1f3e9 + 4201c45 commit 63c646b

11 files changed

+238
-2
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
## 23.8.2
22
- Fixed rating feedback widget event key for widget closed event
3+
- Added `testingDownloadExperimentInformation:` in remote config interface
4+
- Added `testingGetAllExperimentInfo:` in remote config interface
35

46
## 23.8.1
57
- Expanded feedback widget functionality. Added ability to use rating widgets.

Countly-PL.podspec

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ Pod::Spec.new do |s|
1717

1818
s.subspec 'Core' do |core|
1919
core.source_files = '*.{h,m}'
20-
core.public_header_files = 'Countly.h', 'CountlyUserDetails.h', 'CountlyConfig.h', 'CountlyFeedbackWidget.h', 'CountlyRCData.h', 'CountlyRemoteConfig.h', 'CountlyViewTracking.h'
20+
core.public_header_files = 'Countly.h', 'CountlyUserDetails.h', 'CountlyConfig.h', 'CountlyFeedbackWidget.h', 'CountlyRCData.h', 'CountlyRemoteConfig.h', 'CountlyViewTracking.h', 'CountlyExperimentInformation.h'
2121
core.preserve_path = 'countly_dsym_uploader.sh'
2222
core.ios.frameworks = ['Foundation', 'UIKit', 'UserNotifications', 'CoreLocation', 'WebKit', 'CoreTelephony', 'WatchConnectivity']
2323
end

Countly.podspec

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ Pod::Spec.new do |s|
1717

1818
s.subspec 'Core' do |core|
1919
core.source_files = '*.{h,m}'
20-
core.public_header_files = 'Countly.h', 'CountlyUserDetails.h', 'CountlyConfig.h', 'CountlyFeedbackWidget.h', 'CountlyRCData.h', 'CountlyRemoteConfig.h', 'CountlyViewTracking.h'
20+
core.public_header_files = 'Countly.h', 'CountlyUserDetails.h', 'CountlyConfig.h', 'CountlyFeedbackWidget.h', 'CountlyRCData.h', 'CountlyRemoteConfig.h', 'CountlyViewTracking.h', 'CountlyExperimentInformation.h'
2121
core.preserve_path = 'countly_dsym_uploader.sh'
2222
core.ios.frameworks = ['Foundation', 'UIKit', 'UserNotifications', 'CoreLocation', 'WebKit', 'CoreTelephony', 'WatchConnectivity']
2323
end

Countly.xcodeproj/project.pbxproj

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
1A3A576529ED47BD0041B7BE /* CountlyServerConfig.h in Headers */ = {isa = PBXBuildFile; fileRef = 1A3A576429ED47B50041B7BE /* CountlyServerConfig.h */; };
1616
1A423E9E2A271E46008C4757 /* CountlyRCData.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A423E9D2A271E46008C4757 /* CountlyRCData.m */; };
1717
1A423EA02A271FE0008C4757 /* CountlyRCData.h in Headers */ = {isa = PBXBuildFile; fileRef = 1A423E9F2A271E52008C4757 /* CountlyRCData.h */; settings = {ATTRIBUTES = (Public, ); }; };
18+
1A478D032AB314750056A5E7 /* CountlyExperimentInformation.h in Headers */ = {isa = PBXBuildFile; fileRef = 1A9027FF2AB197C00044EBCF /* CountlyExperimentInformation.h */; settings = {ATTRIBUTES = (Public, ); }; };
19+
1A9027FE2AB197B50044EBCF /* CountlyExperimentInformation.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A9027FD2AB197B50044EBCF /* CountlyExperimentInformation.m */; };
1820
1ACA5DC12A309E7F001F770B /* CountlyRemoteConfigInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 1ACA5DBF2A309E7F001F770B /* CountlyRemoteConfigInternal.h */; };
1921
1ACA5DC22A309E7F001F770B /* CountlyRemoteConfigInternal.m in Sources */ = {isa = PBXBuildFile; fileRef = 1ACA5DC02A309E7F001F770B /* CountlyRemoteConfigInternal.m */; };
2022
3B20A9872245225A00E3D7AE /* Countly.h in Headers */ = {isa = PBXBuildFile; fileRef = 3B20A9852245225A00E3D7AE /* Countly.h */; settings = {ATTRIBUTES = (Public, ); }; };
@@ -64,6 +66,8 @@
6466
1A3A576429ED47B50041B7BE /* CountlyServerConfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CountlyServerConfig.h; sourceTree = "<group>"; };
6567
1A423E9D2A271E46008C4757 /* CountlyRCData.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CountlyRCData.m; sourceTree = "<group>"; };
6668
1A423E9F2A271E52008C4757 /* CountlyRCData.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CountlyRCData.h; sourceTree = "<group>"; };
69+
1A9027FD2AB197B50044EBCF /* CountlyExperimentInformation.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CountlyExperimentInformation.m; sourceTree = "<group>"; };
70+
1A9027FF2AB197C00044EBCF /* CountlyExperimentInformation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CountlyExperimentInformation.h; sourceTree = "<group>"; };
6771
1ACA5DBF2A309E7F001F770B /* CountlyRemoteConfigInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CountlyRemoteConfigInternal.h; sourceTree = "<group>"; };
6872
1ACA5DC02A309E7F001F770B /* CountlyRemoteConfigInternal.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CountlyRemoteConfigInternal.m; sourceTree = "<group>"; };
6973
3B20A9822245225A00E3D7AE /* Countly.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Countly.framework; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -120,6 +124,8 @@
120124
3B20A9782245225A00E3D7AE = {
121125
isa = PBXGroup;
122126
children = (
127+
1A9027FF2AB197C00044EBCF /* CountlyExperimentInformation.h */,
128+
1A9027FD2AB197B50044EBCF /* CountlyExperimentInformation.m */,
123129
1A31106E2A7141AF001CB507 /* CountlyViewTracking.h */,
124130
1A31106F2A7141AF001CB507 /* CountlyViewTracking.m */,
125131
1A3110642A7128DC001CB507 /* CountlyViewData.h */,
@@ -186,6 +192,7 @@
186192
isa = PBXHeadersBuildPhase;
187193
buildActionMask = 2147483647;
188194
files = (
195+
1A478D032AB314750056A5E7 /* CountlyExperimentInformation.h in Headers */,
189196
3B20A9D32245228700E3D7AE /* CountlyPushNotifications.h in Headers */,
190197
3B20A9C42245228700E3D7AE /* CountlyUserDetails.h in Headers */,
191198
3B20A9CA2245228700E3D7AE /* CountlyConfig.h in Headers */,
@@ -301,6 +308,7 @@
301308
3B20A9B42245228700E3D7AE /* CountlyPushNotifications.m in Sources */,
302309
3B20A9C92245228700E3D7AE /* CountlyUserDetails.m in Sources */,
303310
3B20A9D12245228700E3D7AE /* CountlyConfig.m in Sources */,
311+
1A9027FE2AB197B50044EBCF /* CountlyExperimentInformation.m in Sources */,
304312
3B20A9C82245228700E3D7AE /* CountlyViewTrackingInternal.m in Sources */,
305313
3B20A9D22245228700E3D7AE /* CountlyLocationManager.m in Sources */,
306314
);

CountlyExperimentInformation.h

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// CountlyExperimentInfo.h
2+
//
3+
// This code is provided under the MIT License.
4+
//
5+
// Please visit www.count.ly for more information.
6+
7+
#import <Foundation/Foundation.h>
8+
9+
@interface CountlyExperimentInformation : NSObject
10+
11+
@property (nonatomic, readonly) NSString* experimentID;
12+
@property (nonatomic, readonly) NSString* experimentName;
13+
@property (nonatomic, readonly) NSString* experimentDescription;
14+
@property (nonatomic, readonly) NSString* currentVariant;
15+
@property (nonatomic, readonly) NSDictionary* variants;
16+
17+
18+
- (instancetype)initWithID:(NSString*)experimentID experimentName:(NSString*)experimentName experimentDescription:(NSString*)experimentDescription currentVariant:(NSString*)currentVariant variants:(NSDictionary*)variants;
19+
20+
@end
21+
22+
23+

CountlyExperimentInformation.m

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
// CountlyExperimentInfo.m
2+
//
3+
// This code is provided under the MIT License.
4+
//
5+
// Please visit www.count.ly for more information.
6+
7+
#import "CountlyExperimentInformation.h"
8+
9+
@interface CountlyExperimentInformation ()
10+
@property (nonatomic) NSString* experimentID;
11+
@property (nonatomic) NSString* experimentName;
12+
@property (nonatomic) NSString* experimentDescription;
13+
@property (nonatomic) NSString* currentVariant;
14+
@property (nonatomic) NSDictionary* variants;
15+
@end
16+
17+
18+
@implementation CountlyExperimentInformation
19+
20+
- (instancetype)init
21+
{
22+
if (self = [super init])
23+
{
24+
}
25+
26+
return self;
27+
}
28+
29+
- (instancetype)initWithID:(NSString*)experimentID experimentName:(NSString*)experimentName experimentDescription:(NSString*)experimentDescription currentVariant:(NSString*)currentVariant variants:(NSDictionary*)variants
30+
{
31+
if (self = [super init])
32+
{
33+
self.experimentID = experimentID;
34+
self.experimentName = experimentName;
35+
self.experimentDescription = experimentDescription;
36+
self.currentVariant = currentVariant;
37+
self.variants = variants;
38+
}
39+
40+
return self;
41+
}
42+
43+
44+
@end

CountlyRemoteConfig.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
#import <Foundation/Foundation.h>
88
#import "CountlyRCData.h"
9+
#import "CountlyExperimentInformation.h"
910

1011
@interface CountlyRemoteConfig : NSObject
1112

@@ -38,6 +39,9 @@
3839

3940
- (void)testingEnrollIntoVariant:(NSString *)key variantName:(NSString *)variantName completionHandler:(RCVariantCallback)completionHandler;
4041

42+
- (void) testingDownloadExperimentInformation:(RCVariantCallback)completionHandler;
43+
- (NSDictionary<NSString*, CountlyExperimentInformation*> *) testingGetAllExperimentInfo;
44+
4145
- (void)clearAll;
4246

4347
@end

CountlyRemoteConfig.m

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,19 @@ - (void)downloadOmittingKeys:(NSArray *)omitKeys completionHandler:(RCDownloadCa
113113
[CountlyRemoteConfigInternal.sharedInstance downloadValuesForKeys:nil omitKeys:omitKeys completionHandler:completionHandler];
114114
}
115115

116+
- (void) testingDownloadExperimentInformation:(RCVariantCallback)completionHandler;
117+
{
118+
CLY_LOG_I(@"%s %@", __FUNCTION__, completionHandler);
119+
120+
[CountlyRemoteConfigInternal.sharedInstance testingDownloadExperimentInformation:completionHandler];
121+
}
122+
123+
- (NSDictionary<NSString*, CountlyExperimentInformation*> *) testingGetAllExperimentInfo
124+
{
125+
CLY_LOG_I(@"%s", __FUNCTION__);
126+
return [CountlyRemoteConfigInternal.sharedInstance testingGetAllExperimentInfo];
127+
}
128+
116129
- (void)clearAll
117130
{
118131
[CountlyRemoteConfigInternal.sharedInstance clearAll];

CountlyRemoteConfigInternal.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@
3232
- (void)testingDownloadAllVariants:(RCVariantCallback)completionHandler;
3333
- (void)testingEnrollIntoVariant:(NSString *)key variantName:(NSString *)variantName completionHandler:(RCVariantCallback)completionHandler;
3434

35+
- (void) testingDownloadExperimentInformation:(RCVariantCallback)completionHandler;
36+
- (NSDictionary<NSString*, CountlyExperimentInformation*> *) testingGetAllExperimentInfo;
37+
3538
- (NSDictionary<NSString*, CountlyRCData *> *)getAllValues;
3639
- (void)enrollIntoABTestsForKeys:(NSArray *)keys;
3740
- (void)exitABTestsForKeys:(NSArray *)keys;

CountlyRemoteConfigInternal.m

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
NSString* const kCountlyRCKeyFetchRemoteConfig = @"fetch_remote_config";
1010
NSString* const kCountlyRCKeyFetchVariant = @"ab_fetch_variants";
1111
NSString* const kCountlyRCKeyEnrollVariant = @"ab_enroll_variant";
12+
NSString* const kCountlyRCKeyFetchExperiments = @"ab_fetch_experiments";
1213
NSString* const kCountlyRCKeyVariant = @"variant";
1314
NSString* const kCountlyRCKeyKey = @"key";
1415
NSString* const kCountlyRCKeyKeys = @"keys";
@@ -27,6 +28,7 @@
2728
@interface CountlyRemoteConfigInternal ()
2829
@property (nonatomic) NSDictionary* localCachedVariants;
2930
@property (nonatomic) NSDictionary<NSString *, CountlyRCData *>* cachedRemoteConfig;
31+
@property (nonatomic) NSDictionary<NSString*, CountlyExperimentInformation*> * localCachedExperiments;
3032
@end
3133

3234
@implementation CountlyRemoteConfigInternal
@@ -49,6 +51,8 @@ - (instancetype)init
4951
self.cachedRemoteConfig = [CountlyPersistency.sharedInstance retrieveRemoteConfig] ;
5052

5153
self.remoteConfigGlobalCallbacks = [[NSMutableArray alloc] init];
54+
55+
self.localCachedExperiments = NSMutableDictionary.new;
5256
}
5357

5458
return self;
@@ -448,6 +452,7 @@ - (void)testingDownloadAllVariants:(RCVariantCallback)completionHandler
448452
}];
449453
}
450454

455+
451456
- (void)testingDownloadAllVariantsInternal:(void (^)(CLYRequestResult response, NSDictionary* variants, NSError * error))completionHandler
452457
{
453458
if (!CountlyServerConfig.sharedInstance.networkingEnabled)
@@ -649,6 +654,139 @@ - (NSURLRequest *)downloadVariantsRequest
649654
}
650655
}
651656

657+
- (void) testingDownloadExperimentInformation:(RCVariantCallback)completionHandler
658+
{
659+
if (!CountlyConsentManager.sharedInstance.consentForRemoteConfig)
660+
{
661+
CLY_LOG_D(@"'testingDownloadExperimentInformation' is aborted: RemoteConfig consent requires");
662+
return;
663+
}
664+
if (CountlyDeviceInfo.sharedInstance.isDeviceIDTemporary)
665+
{
666+
CLY_LOG_D(@"'testingDownloadExperimentInformation' is aborted: Due to temporary device id");
667+
return;
668+
}
669+
670+
CLY_LOG_D(@"Download experiments info...");
671+
672+
[self testingDownloaExperimentInfoInternal:^(CLYRequestResult response, NSDictionary *experimentInfo,NSError *error)
673+
{
674+
if (!error)
675+
{
676+
self.localCachedExperiments = experimentInfo;
677+
CLY_LOG_D(@"Download experiments info is successful. \n%@", experimentInfo);
678+
679+
}
680+
else
681+
{
682+
CLY_LOG_W(@"Download experiments info failed: %@", error);
683+
}
684+
685+
if (completionHandler)
686+
completionHandler(response, error);
687+
}];
688+
}
689+
690+
691+
- (void)testingDownloaExperimentInfoInternal:(void (^)(CLYRequestResult response, NSDictionary* experimentsInfo, NSError * error))completionHandler
692+
{
693+
if (!CountlyServerConfig.sharedInstance.networkingEnabled)
694+
{
695+
CLY_LOG_D(@"'testingDownloaExperimentInfoInternal' is aborted: SDK Networking is disabled from server config!");
696+
return;
697+
}
698+
if (!completionHandler)
699+
return;
700+
701+
NSURLRequest* request = [self downloadExperimentInfoRequest];
702+
NSURLSessionTask* task = [NSURLSession.sharedSession dataTaskWithRequest:request completionHandler:^(NSData* data, NSURLResponse* response, NSError* error)
703+
{
704+
705+
NSMutableDictionary<NSString*, CountlyExperimentInformation*> * experiments = NSMutableDictionary.new;
706+
707+
if (!error)
708+
{
709+
710+
NSArray* experimentsInfo = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error];
711+
[experimentsInfo enumerateObjectsUsingBlock:^(NSDictionary* value, NSUInteger idx, BOOL * stop)
712+
{
713+
CountlyExperimentInformation* experimentInfo = [[CountlyExperimentInformation alloc] initWithID:value[@"id"] experimentName:value[@"name"] experimentDescription:value[@"description"] currentVariant:value[@"currentVariant"] variants:value[@"variants"]];
714+
experiments[experimentInfo.experimentID] = experimentInfo;
715+
716+
}];
717+
}
718+
719+
if (!error)
720+
{
721+
if (((NSHTTPURLResponse*)response).statusCode != 200)
722+
{
723+
NSMutableDictionary* userInfo = experiments.mutableCopy;
724+
userInfo[NSLocalizedDescriptionKey] = @"Fetch variants general API error";
725+
error = [NSError errorWithDomain:kCountlyErrorDomain code:CLYErrorRemoteConfigGeneralAPIError userInfo:userInfo];
726+
}
727+
}
728+
729+
if (error)
730+
{
731+
CLY_LOG_D(@"Download experiments Request <%p> failed!\nError: %@", request, error);
732+
733+
dispatch_async(dispatch_get_main_queue(), ^
734+
{
735+
completionHandler(CLYResponseError, nil, error);
736+
});
737+
738+
return;
739+
}
740+
741+
CLY_LOG_D(@"Download experiments Request <%p> successfully completed.", request);
742+
743+
dispatch_async(dispatch_get_main_queue(), ^
744+
{
745+
completionHandler(CLYResponseSuccess, experiments, nil);
746+
});
747+
}];
748+
749+
[task resume];
750+
751+
CLY_LOG_D(@"Download experiments Request <%p> started:\n[%@] %@", (id)request, request.HTTPMethod, request.URL.absoluteString);
752+
}
753+
754+
- (NSURLRequest *)downloadExperimentInfoRequest
755+
{
756+
NSString* queryString = [CountlyConnectionManager.sharedInstance queryEssentials];
757+
758+
queryString = [queryString stringByAppendingFormat:@"&%@=%@", kCountlyQSKeyMethod, kCountlyRCKeyFetchExperiments];
759+
760+
if (CountlyConsentManager.sharedInstance.consentForSessions)
761+
{
762+
queryString = [queryString stringByAppendingFormat:@"&%@=%@", kCountlyQSKeyMetrics, [CountlyDeviceInfo metrics]];
763+
}
764+
765+
queryString = [CountlyConnectionManager.sharedInstance appendChecksum:queryString];
766+
767+
NSString* serverOutputSDKEndpoint = [CountlyConnectionManager.sharedInstance.host stringByAppendingFormat:@"%@%@",
768+
kCountlyEndpointO,
769+
kCountlyEndpointSDK];
770+
771+
if (CountlyConnectionManager.sharedInstance.alwaysUsePOST)
772+
{
773+
NSMutableURLRequest* request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:serverOutputSDKEndpoint]];
774+
request.HTTPMethod = @"POST";
775+
request.HTTPBody = [queryString cly_dataUTF8];
776+
return request.copy;
777+
}
778+
else
779+
{
780+
NSString* withQueryString = [serverOutputSDKEndpoint stringByAppendingFormat:@"?%@", queryString];
781+
NSURLRequest* request = [NSURLRequest requestWithURL:[NSURL URLWithString:withQueryString]];
782+
return request;
783+
}
784+
}
785+
- (NSDictionary<NSString*, CountlyExperimentInformation*> *) testingGetAllExperimentInfo
786+
{
787+
return self.localCachedExperiments;
788+
}
789+
652790
- (NSURLRequest *)enrollInVarianRequestForKey:(NSString *)key variantName:(NSString *)variantName
653791
{
654792
NSString* queryString = [CountlyConnectionManager.sharedInstance queryEssentials];
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../CountlyExperimentInformation.h

0 commit comments

Comments
 (0)