Skip to content

Commit

Permalink
feat: Event upload bypass option
Browse files Browse the repository at this point in the history
* Implement event upload bypass option

Allows clients to choose to pass events only to kits or (by default) also upload to mParticle's backend. This is chosen on an event-by-event basis by simply setting the boolean `shouldUpload` property on the event to YES or NO (default YES).

* Propagate shouldUploadEvent to expanded commerce events

* Add unit tests for upload bypass

* Add debug log when skip saving message due to upload bypass
  • Loading branch information
einsteinx2 committed Jul 29, 2021
1 parent e41578d commit e58ae23
Show file tree
Hide file tree
Showing 8 changed files with 84 additions and 0 deletions.
59 changes: 59 additions & 0 deletions UnitTests/MPPersistenceControllerTests.mm
Original file line number Diff line number Diff line change
Expand Up @@ -858,4 +858,63 @@ - (void)testSaveNilMessage {
XCTAssertNil(e);
}

- (void)testShouldUploadMessageToMParticle {
MParticle *instance = [MParticle sharedInstance];
NSDictionary *messageDictionary = @{
@"location": @"17 Cherry Tree Lane",
@"hardwareId": @"IDFA:a5d934n0-232f-4afc-2e9a-3832d95zc702"
};
NSData *messageData = [NSJSONSerialization dataWithJSONObject:messageDictionary options:0 error:nil];
NSNumber *sessionId = @17;
NSString *uuid = @"uuid";
MPMessage *message = [[MPMessage alloc] initWithSessionId:sessionId
messageId:1
UUID:uuid
messageType:@"test"
messageData:messageData
timestamp:[[NSDate date] timeIntervalSince1970]
uploadStatus:MPUploadStatusBatch
userId:@1
dataPlanId:nil
dataPlanVersion:nil];

[instance.persistenceController saveMessage:message];
NSDictionary *messages = [instance.persistenceController fetchMessagesForUploading];
XCTAssertEqual(messages.count, 1);
NSDictionary *messagesForMpid = messages[message.userId];
XCTAssertEqual(messagesForMpid.count, 1);
NSDictionary *messagesForSessionId = messagesForMpid[sessionId];
XCTAssertEqual(messagesForSessionId.count, 1);
NSDictionary *messsagesForDataPlanId = messagesForSessionId[@"0"];
XCTAssertEqual(messsagesForDataPlanId.count, 1);
NSArray *messagesForDataPlanVersion = messsagesForDataPlanId[@0];
XCTAssertEqual(messagesForDataPlanVersion.count, 1);
MPMessage *messageForUpload = messagesForDataPlanVersion[0];
XCTAssertEqualObjects(message, messageForUpload);
}

- (void)testShouldNotUploadMessageToMParticle {
MParticle *instance = [MParticle sharedInstance];
NSDictionary *messageDictionary = @{
@"location": @"17 Cherry Tree Lane",
@"hardwareId": @"IDFA:a5d934n0-232f-4afc-2e9a-3832d95zc702"
};
NSData *messageData = [NSJSONSerialization dataWithJSONObject:messageDictionary options:0 error:nil];
MPMessage *message = [[MPMessage alloc] initWithSessionId:@17
messageId:1
UUID:@"uuid"
messageType:@"test"
messageData:messageData
timestamp:[[NSDate date] timeIntervalSince1970]
uploadStatus:MPUploadStatusBatch
userId:@1
dataPlanId:nil
dataPlanVersion:nil];
message.shouldUploadEvent = NO;

[instance.persistenceController saveMessage:message];
NSDictionary *messages = [instance.persistenceController fetchMessagesForUploading];
XCTAssertEqual(messages.count, 0);
}

@end
1 change: 1 addition & 0 deletions mParticle-Apple-SDK/Data Model/MPMessage.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
@property (nonatomic, strong, nullable) NSString *dataPlanId;
@property (nonatomic, strong, nullable) NSNumber *dataPlanVersion;
@property (nonatomic, unsafe_unretained) MPUploadStatus uploadStatus;
@property (nonatomic) BOOL shouldUploadEvent;

- (nonnull instancetype)initWithSessionId:(nullable NSNumber *)sessionId
messageId:(int64_t)messageId
Expand Down
7 changes: 7 additions & 0 deletions mParticle-Apple-SDK/Data Model/MPMessage.m
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ - (instancetype)initWithSessionId:(NSNumber *)sessionId messageId:(int64_t)messa
_userId = userId;
_dataPlanId = dataPlanId;
_dataPlanVersion = dataPlanVersion;
_shouldUploadEvent = YES;
}

return self;
Expand Down Expand Up @@ -87,6 +88,7 @@ - (BOOL)isEqual:(MPMessage *)object {
_timestamp == object.timestamp &&
[_messageType isEqualToString:object.messageType] &&
[_messageData isEqualToData:object.messageData] &&
_shouldUploadEvent == object.shouldUploadEvent &&
dataPlanIdEqual &&
dataPlanVersionEqual;

Expand All @@ -105,6 +107,7 @@ - (id)copyWithZone:(NSZone *)zone {
userId:_userId
dataPlanId:[_dataPlanId copy]
dataPlanVersion:[_dataPlanVersion copy]];
copyObject.shouldUploadEvent = _shouldUploadEvent;

return copyObject;
}
Expand All @@ -121,6 +124,7 @@ - (void)encodeWithCoder:(NSCoder *)coder {
[coder encodeInt64:_userId.longLongValue forKey:@"mpid"];
[coder encodeObject:self.dataPlanId forKey:@"dataPlanId"];
[coder encodeObject:self.dataPlanVersion forKey:@"dataPlanVersion"];
[coder encodeBool:self.shouldUploadEvent forKey:@"shouldUploadEvent"];
}

- (id)initWithCoder:(NSCoder *)coder {
Expand All @@ -134,6 +138,9 @@ - (id)initWithCoder:(NSCoder *)coder {
userId:@([coder decodeInt64ForKey:@"mpid"])
dataPlanId:[coder decodeObjectOfClass:[NSString class] forKey:@"dataPlanId"]
dataPlanVersion:[coder decodeObjectOfClass:[NSNumber class] forKey:@"dataPlanVersion"]];
if ([coder containsValueForKey:@"shouldUploadEvent"]) {
_shouldUploadEvent = [coder decodeBoolForKey:@"shouldUploadEvent"];
}

return self;
}
Expand Down
4 changes: 4 additions & 0 deletions mParticle-Apple-SDK/Ecommerce/MPCommerceEvent.mm
Original file line number Diff line number Diff line change
Expand Up @@ -627,6 +627,7 @@ - (NSDictionary *)dictionaryRepresentation {

for (product in _productsList) {
event = [[MPEvent alloc] initWithName:eventName type:MPEventTypeTransaction];
event.shouldUploadEvent = self.shouldUploadEvent;
eventInfo = [[NSMutableDictionary alloc] initWithCapacity:4];

productDictionary = [product beautifiedDictionaryRepresentation];
Expand Down Expand Up @@ -655,6 +656,7 @@ - (NSDictionary *)dictionaryRepresentation {
if (purchaseOrRefund) {
eventName = [NSString stringWithFormat:@"eCommerce - %@ - Total", actionName];
event = [[MPEvent alloc] initWithName:eventName type:MPEventTypeTransaction];
event.shouldUploadEvent = self.shouldUploadEvent;

eventInfo = [[NSMutableDictionary alloc] initWithCapacity:4];
eventInfo[kMPExpCECurrency] = self.currency ? : @"USD";
Expand Down Expand Up @@ -698,6 +700,7 @@ - (NSDictionary *)dictionaryRepresentation {
case MPCommerceEventKindPromotion: {
eventName = [NSString stringWithFormat:@"eCommerce - %@ - Item", [self.promotionContainer actionNameForAction:self.promotionContainer.action]];
event = [[MPEvent alloc] initWithName:eventName type:MPEventTypeTransaction];
event.shouldUploadEvent = self.shouldUploadEvent;
eventInfo = [[NSMutableDictionary alloc] initWithCapacity:4];

NSDictionary *promotionDictionary = [self.promotionContainer beautifiedDictionaryRepresentation];
Expand Down Expand Up @@ -726,6 +729,7 @@ - (NSDictionary *)dictionaryRepresentation {
if (listedProducts.count > 0) {
for (product in listedProducts) {
event = [[MPEvent alloc] initWithName:eventName type:MPEventTypeTransaction];
event.shouldUploadEvent = self.shouldUploadEvent;
eventInfo = [[NSMutableDictionary alloc] initWithCapacity:4];
eventInfo[kMPExpCEProductImpressionList] = listName;

Expand Down
2 changes: 2 additions & 0 deletions mParticle-Apple-SDK/Event/MPBaseEvent.m
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ - (instancetype)initWithEventType:(MPEventType)type {
_customAttributes = nil;
_customFlags = nil;
_shouldBeginSession = YES;
_shouldUploadEvent = YES;
self.type = type;

return self;
Expand Down Expand Up @@ -161,6 +162,7 @@ - (id)copyWithZone:(NSZone *)zone {
copyObject.customAttributes = [_customAttributes copy];
copyObject.messageType = _messageType;
copyObject.timestamp = [_timestamp copy];
copyObject.shouldUploadEvent = _shouldUploadEvent;

for (NSString *key in [_customFlags allKeys]) {
[copyObject addCustomFlags:[_customFlags[key] copy] withKey:[key copy]];
Expand Down
5 changes: 5 additions & 0 deletions mParticle-Apple-SDK/Include/MPBaseEvent.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,11 @@ NS_ASSUME_NONNULL_BEGIN
*/
@property (nonatomic) BOOL shouldBeginSession;

/**
Whether this event should be uploaded to mParticle when logged or only passed to kits (defaults to YES).
*/
@property (nonatomic) BOOL shouldUploadEvent;

/**
A Dictionary representation of this instance for uploading the event
Must be overridden by a subclass
Expand Down
1 change: 1 addition & 0 deletions mParticle-Apple-SDK/MPBackendController.mm
Original file line number Diff line number Diff line change
Expand Up @@ -1638,6 +1638,7 @@ - (void)logBaseEvent:(MPBaseEvent *)event completionHandler:(void (^)(MPBaseEven
messageBuilder = [messageBuilder withLocation:[MParticle sharedInstance].stateMachine.location];
#endif
MPMessage *message = [messageBuilder build];
message.shouldUploadEvent = event.shouldUploadEvent;

[self saveMessage:message updateSession:YES];

Expand Down
5 changes: 5 additions & 0 deletions mParticle-Apple-SDK/Persistence/MPPersistenceController.mm
Original file line number Diff line number Diff line change
Expand Up @@ -1644,6 +1644,11 @@ - (void)saveIntegrationAttributes:(nonnull MPIntegrationAttributes *)integration
}

- (void)saveMessage:(MPMessage *)message {
if (!message.shouldUploadEvent) {
MPILogDebug(@"Not saving message for event because shouldUploadEvent was set to NO, message id: %lld, type: %@", message.messageId, message.messageType);
return;
}

NSInteger maxBytes = [MPPersistenceController maxBytesPerEvent:message.messageType];
if (message == nil || message.messageData.length > maxBytes) {
MPILogError(@"Unable to save message that is nil or exceeds max message size!");
Expand Down

0 comments on commit e58ae23

Please sign in to comment.