Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NR-186415 rewrote the persistence in the new event system #190

Closed
wants to merge 11 commits into from
1 change: 1 addition & 0 deletions Agent/Analytics/Constants.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ extern NSString *const kNRMA_Val_errorType_Network;

extern NSString *const kNRMA_Attrib_file;
extern NSString *const kNRMA_Attrib_file_private;
extern NSString *const kNRMA_EventStoreFilename;


// Integer Analytics Constants
Expand Down
3 changes: 2 additions & 1 deletion Agent/Analytics/Constants.m
Original file line number Diff line number Diff line change
Expand Up @@ -89,5 +89,6 @@
NSString * const kNRMA_Val_errorType_Network = @"NetworkFailure";


NSString * const kNRMA_Attrib_file = @"attributes.txt";
NSString * const kNRMA_Attrib_file = @"attributes.txt";
NSString * const kNRMA_Attrib_file_private = @"privateAttributes.txt";
NSString * const kNRMA_EventStoreFilename = @"eventsStore.txt";
31 changes: 15 additions & 16 deletions Agent/Analytics/NRMAAnalytics.mm
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,6 @@ @implementation NRMAAnalytics
id<AttributeValidatorProtocol> _attributeValidator;
}

static NSString* const eventStoreFilename = @"eventsStore.txt";

static PersistentStore<std::string,BaseValue>* __attributeStore;
+ (PersistentStore<std::string, BaseValue> &) attributeDupStore
{
Expand Down Expand Up @@ -103,11 +101,8 @@ - (id) initWithSessionStartTimeMS:(long long) sessionStartTime {
if(self){
// Handle New Event System NRMAnalytics Constructor
if([NRMAFlags shouldEnableNewEventSystem]){
NSString *filename = [[NewRelicInternalUtils getStorePath] stringByAppendingPathComponent:eventStoreFilename];

PersistentEventStore *eventStore = [[PersistentEventStore alloc] initWithFilename:filename andMinimumDelay:30];

_eventManager = [[NRMAEventManager alloc] initWithPersistentStore:eventStore];
_eventManager = [[NRMAEventManager alloc] init];
_attributeValidator = [[BlockAttributeValidator alloc] initWithNameValidator:^BOOL(NSString *name) {
if ([name length] == 0) {
NRLOG_ERROR(@"invalid attribute: name length = 0");
Expand Down Expand Up @@ -1005,10 +1000,9 @@ + (NSString*) getLastSessionsAttributes {
}
}

+ (NSString*) getLastSessionsEvents{
+ (NSString*) getLastSessionsEvents {
if([NRMAFlags shouldEnableNewEventSystem]) {
NSString *filename = [[NewRelicInternalUtils getStorePath] stringByAppendingPathComponent:eventStoreFilename];
return [NRMAEventManager getLastSessionEventsFromFilename:filename];
return [NRMAEventManager getLastSessionEventsString];
} else {
try {
auto events = AnalyticsController::fetchDuplicatedEvents([self eventDupStore], true);
Expand All @@ -1035,13 +1029,18 @@ + (NSString*) getLastSessionsEvents{

+ (void) clearDuplicationStores
{
try {
[self attributeDupStore].clear();
[self eventDupStore].clear();
} catch (std::exception& e) {
NRLOG_VERBOSE(@"Failed to clear dup stores: %s",e.what());
} catch(...) {
NRLOG_VERBOSE(@"Failed to clear dup stores.");
if([NRMAFlags shouldEnableNewEventSystem]){
[NRMAEventManager clearDuplicationStores];
[NRMASAM clearDuplicationStores];
} else {
try {
[self attributeDupStore].clear();
[self eventDupStore].clear();
} catch (std::exception& e) {
NRLOG_VERBOSE(@"Failed to clear dup stores: %s",e.what());
} catch(...) {
NRLOG_VERBOSE(@"Failed to clear dup stores.");
}
}
}

Expand Down
4 changes: 3 additions & 1 deletion Agent/Analytics/NRMAEventManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,16 @@ NS_ASSUME_NONNULL_BEGIN

@interface NRMAEventManager : NSObject

- (instancetype)initWithPersistentStore:(PersistentEventStore *)store;
- (void)setMaxEventBufferSize:(NSUInteger)size;
- (void)setMaxEventBufferTimeInSeconds:(NSUInteger)seconds;
- (BOOL)didReachMaxQueueTime:(NSTimeInterval)currentTimeMilliseconds;
- (BOOL)addEvent:(id<NRMAAnalyticEventProtocol>)event;
- (void)empty;
- (nullable NSString *)getEventJSONStringWithError:(NSError *__autoreleasing *)error clearEvents:(BOOL)clearEvents;

+ (NSString *)getLastSessionEventsString;
+ (NSMutableArray<NRMAAnalyticEventProtocol> *)getLastSessionEventsArray;
+ (void) clearDuplicationStores;
+ (nullable NSString *)getLastSessionEventsFromFilename:(NSString *)filename;
@end

Expand Down
75 changes: 66 additions & 9 deletions Agent/Analytics/NRMAEventManager.m
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
#import "NRMARequestEvent.h"
#import "NRMANetworkErrorEvent.h"
#import "NRMAAgentConfiguration.h"
#import "NewRelicInternalUtils.h"
#import "Constants.h"

static const NSUInteger kDefaultBufferSize = 1000;
static const NSUInteger kDefaultBufferTimeSeconds = 600; // 10 Minutes
Expand All @@ -29,19 +31,38 @@ @implementation NRMAEventManager {

NSUInteger totalAttemptedInserts;
NSTimeInterval oldestEventTimestamp;

PersistentEventStore *_persistentStore;
}

- (nonnull instancetype)initWithPersistentStore:(PersistentEventStore *)store {
static PersistentEventStore* __persistentEventStore;
+ (PersistentEventStore*) persistentEventStore
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
NSString *filename = [[NewRelicInternalUtils getStorePath] stringByAppendingPathComponent:kNRMA_EventStoreFilename];
__persistentEventStore = [[PersistentEventStore alloc] initWithFilename:filename andMinimumDelay:.025];
});
return (__persistentEventStore);
}

- (nonnull instancetype)init {
self = [super init];
if (self) {
events = [[NSMutableArray<NRMAAnalyticEventProtocol> alloc] init];
maxBufferSize = kDefaultBufferSize;
events = [NRMAEventManager getLastSessionEventsArray];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be behind a feature flag to only happen when offline storage is enabled?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it is a good idea to have this as a feature flag but this is separate from offline storage.

Persistence was originally intended to create an event trail for handledExceptions. Now because we believed that events were suppose to persist back into an eventManager and Android agreed they added that and now we should too. This accomplishes the goal of restoring events of an app session that ended unexpectedly.

The way that offline storage currently is CDD'd to work is by storing the data of failed network request into separate files and then sending them all as soon as we send a successful request. There are talks about combining these two things but I haven't heard anything conclusive.

maxBufferSize = [NRMAAgentConfiguration getMaxEventBufferSize];
maxBufferTimeSeconds = [NRMAAgentConfiguration getMaxEventBufferTime];
totalAttemptedInserts = 0;
oldestEventTimestamp = 0;
}
return self;
}
- (nonnull instancetype)initWithFilename:(NSString*) filename {
self = [super init];
if (self) {
events = [NRMAEventManager getLastSessionEventsArray];
maxBufferSize = [NRMAAgentConfiguration getMaxEventBufferSize];
maxBufferTimeSeconds = [NRMAAgentConfiguration getMaxEventBufferTime];
totalAttemptedInserts = 0;
oldestEventTimestamp = 0;
_persistentStore = store;
}
return self;
}
Expand Down Expand Up @@ -85,7 +106,7 @@ - (BOOL)addEvent:(id<NRMAAnalyticEventProtocol>)event {
if (events.count < maxBufferSize) {
[events addObject:event];

[_persistentStore setObject:event forKey:[self createKeyForEvent:event]];
[[NRMAEventManager persistentEventStore] setObject:event forKey:[self createKeyForEvent:event]];

if(events.count == 1) {
oldestEventTimestamp = event.timestamp;
Expand All @@ -98,7 +119,7 @@ - (BOOL)addEvent:(id<NRMAAnalyticEventProtocol>)event {
[events removeObjectAtIndex:evictionIndex];
[events addObject:event];

[_persistentStore removeObjectForKey:[self createKeyForEvent:event]];
[[NRMAEventManager persistentEventStore] removeObjectForKey:[self createKeyForEvent:event]];
}
}
}
Expand All @@ -113,7 +134,7 @@ - (NSString *)createKeyForEvent:(id<NRMAAnalyticEventProtocol>)event {
- (void)empty {
@synchronized (events) {
[events removeAllObjects];
[_persistentStore clearAll];
[[NRMAEventManager persistentEventStore] clearAll];
oldestEventTimestamp = 0;
totalAttemptedInserts = 0;
}
Expand Down Expand Up @@ -144,6 +165,42 @@ - (nullable NSString *)getEventJSONStringWithError:(NSError *__autoreleasing *)e
return eventJsonString;
}

+ (NSMutableArray<NRMAAnalyticEventProtocol> *)getLastSessionEventsArray
{
NSDictionary *lastSessionEvents = [[NRMAEventManager persistentEventStore] getLastSessionEvents];
NSMutableArray<NRMAAnalyticEventProtocol> * events = (NSMutableArray<NRMAAnalyticEventProtocol> *)[[NSMutableArray alloc] initWithArray:[lastSessionEvents allValues]];
return events;
}

+ (NSString *)getLastSessionEventsString {
NSDictionary *lastSessionEvents = [[NRMAEventManager persistentEventStore] getLastSessionEvents];
NSString *lastSessionEventJsonString = nil;
@synchronized (lastSessionEvents) {
@try {
NSMutableArray *jsonEvents = [[NSMutableArray alloc] init];
for(id<NRMAAnalyticEventProtocol> event in lastSessionEvents.allValues) {
[jsonEvents addObject:[event JSONObject]];

NSData *lastSessionEventJsonData = [NRMAJSON dataWithJSONObject:jsonEvents
options:0
error:nil];
lastSessionEventJsonString = [[NSString alloc] initWithData:lastSessionEventJsonData
encoding:NSUTF8StringEncoding];
}
}
@catch (NSException *e) {
NRLOG_ERROR(@"FAILED TO CREATE LAST SESSION EVENT JSON: %@", e.reason);
}
}

return lastSessionEventJsonString;
}

+ (void) clearDuplicationStores
{
[[NRMAEventManager persistentEventStore] clearAll];
}

+ (NSString *)getLastSessionEventsFromFilename:(NSString *)filename {
NSDictionary *lastSessionEvents = [PersistentEventStore getLastSessionEventsFromFilename:filename];
NSString *lastSessionEventJsonString = nil;
Expand Down
3 changes: 2 additions & 1 deletion Agent/Analytics/NRMASAM.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,11 @@ NS_ASSUME_NONNULL_BEGIN

+ (NSString*) getLastSessionsAttributes;
- (void) clearLastSessionsAnalytics;
- (void) clearPersistedSessionAnalytics;

- (NSString*) sessionAttributeJSONString;
- (BOOL) setLastInteraction:(NSString*)name;

+ (void) clearDuplicationStores;
@end

NS_ASSUME_NONNULL_END
Loading