Skip to content

feat(event processor): Add LogEvent notification support #263

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

Merged
merged 30 commits into from
Oct 4, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
f11dba6
fix existing tests for ep batch changes (wip)
jaeopt Aug 28, 2019
811aca4
fix errors for concurrent event-batch tests
jaeopt Aug 29, 2019
f3fe976
cleanup
jaeopt Aug 30, 2019
8fd9a1d
add tests for non-time flush cases
jaeopt Aug 30, 2019
a2659f1
fix tests for non-time flush cases
jaeopt Aug 30, 2019
8354ae1
fix batch as much as possible when non-batch found in queue
jaeopt Aug 30, 2019
c856b88
flush on batchSize hit
jaeopt Aug 30, 2019
3e24dd8
cleanup
jaeopt Aug 30, 2019
4f672af
fix event flushes for non-timer
jaeopt Sep 3, 2019
68c7732
refactor chagne observer
jaeopt Sep 3, 2019
995aef5
add support for maxQueueSize - configurable
jaeopt Sep 3, 2019
f9db90f
clean up batch on error
jaeopt Sep 4, 2019
78dd3a8
(wip) add log_event notif
jaeopt Sep 4, 2019
1021126
add test for dispatchEvent callbacks
jaeopt Sep 4, 2019
e36ef26
fix test event files to random
jaeopt Sep 4, 2019
7e32722
fix conflicts
jaeopt Sep 4, 2019
0ad4ae1
add test for LOG_EVENT notification
jaeopt Sep 4, 2019
31cc809
add LogEvent notification to event processor
jaeopt Sep 5, 2019
1ae1a3c
cleanup
jaeopt Sep 5, 2019
f379480
fix eventDispatcher configuration for objective-c
jaeopt Sep 5, 2019
bf52c56
fix test for objective-c event dispatcher configuration
jaeopt Sep 5, 2019
c383df8
fix conflicts
jaeopt Sep 9, 2019
d342c69
cleanup demo app code
jaeopt Sep 9, 2019
5c12109
switch unit test order to workaround coverall false reports
jaeopt Sep 19, 2019
753642f
exclude some event-batch tests from OS9
jaeopt Sep 19, 2019
6e65ecf
merge master
jaeopt Sep 23, 2019
eb4c184
turn off coverage from tv tests (coverall not adding up)
jaeopt Sep 23, 2019
b428452
cleanup
jaeopt Sep 24, 2019
a09d51a
Merge branch 'master' into jae/epNotif
jaeopt Sep 24, 2019
ebb3aab
Merge branch 'master' into jae/epNotif
thomaszurkan-optimizely Oct 4, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,8 @@ jobs:
branches:
only:
- master
env: SCHEME=OptimizelySwiftSDK-iOS TEST_SDK=iphonesimulator PLATFORM='iOS Simulator' OS=9.3 NAME='iPad Air'
name: PLATFORM='iOS Simulator' OS=9.3 NAME='iPad Air'
env: SCHEME=OptimizelySwiftSDK-iOS TEST_SDK=iphonesimulator PLATFORM='iOS Simulator' OS=12.1 NAME='iPhone 7'
Copy link
Contributor

Choose a reason for hiding this comment

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

Shouldn't this be in another PR?

name: PLATFORM='iOS Simulator' OS=12.1 NAME='iPhone 7'
install:
- gem install slather --no-document --quiet
- gem install cocoapods -v '1.6.1'
Expand All @@ -80,8 +80,8 @@ jobs:
env: SCHEME=OptimizelySwiftSDK-iOS TEST_SDK=iphonesimulator PLATFORM='iOS Simulator' OS=11.4 NAME='iPhone 7 Plus'
name: PLATFORM='iOS Simulator' OS=11.4 NAME='iPhone 7 Plus'
- <<: *unittests
env: SCHEME=OptimizelySwiftSDK-iOS TEST_SDK=iphonesimulator PLATFORM='iOS Simulator' OS=12.1 NAME='iPhone 7'
name: PLATFORM='iOS Simulator' OS=12.1 NAME='iPhone 7'
env: SCHEME=OptimizelySwiftSDK-iOS TEST_SDK=iphonesimulator PLATFORM='iOS Simulator' OS=9.3 NAME='iPad Air'
name: PLATFORM='iOS Simulator' OS=9.3 NAME='iPad Air'
- <<: *unittests
env: SCHEME=OptimizelySwiftSDK-tvOS TEST_SDK=appletvsimulator PLATFORM='tvOS Simulator' OS=12.1 NAME='Apple TV 4K'
name: PLATFORM='tvOS Simulator' OS=12.1 NAME='Apple TV 4K'
Expand Down
14 changes: 12 additions & 2 deletions DemoObjCApp/AppDelegate.m
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,14 @@ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(
// MARK: - Initialization Examples

-(void)initializeOptimizelySDKAsynchronous {
DefaultEventDispatcher *eventDispacher = [[DefaultEventDispatcher alloc] initWithTimerInterval:1];
DefaultEventDispatcher *eventDispacher = [[DefaultEventDispatcher alloc] initWithBatchSize:10 timerInterval:1 maxQueueSize:1000];

self.optimizely = [[OptimizelyClient alloc] initWithSdkKey:kOptimizelySdkKey logger:nil eventDispatcher:eventDispacher userProfileService:nil periodicDownloadInterval:@(5) defaultLogLevel:OptimizelyLogLevelDebug];
self.optimizely = [[OptimizelyClient alloc] initWithSdkKey:kOptimizelySdkKey
logger:nil
eventDispatcher:eventDispacher
userProfileService:nil
periodicDownloadInterval:@(5)
defaultLogLevel:OptimizelyLogLevelDebug];

[self.optimizely startWithCompletion:^(NSData *data, NSError *error) {
if (error == nil) {
Expand Down Expand Up @@ -126,6 +131,11 @@ -(void)initializeOptimizelySDKWithCustomization {

}];

notifId = [self.optimizely.notificationCenter addLogEventNotificationListenerWithLogEventListener:^(NSString *url,
NSDictionary<NSString *,id> *event) {
NSLog(@"Received logEvent notification: %@ %@", url, event);
}];

[self.optimizely startWithCompletion:^(NSData *data, NSError *error) {
if (error == nil) {
NSLog(@"Optimizely SDK initialized successfully!");
Expand Down
9 changes: 6 additions & 3 deletions DemoSwiftApp/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate {

do {
let datafileJSON = try String(contentsOfFile: localDatafilePath, encoding: .utf8)
try optimizely!.start(datafile: datafileJSON)
try optimizely.start(datafile: datafileJSON)

print("Optimizely SDK initialized successfully!")
} catch {
Expand All @@ -108,7 +108,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
addListeners()

// initialize SDK
optimizely!.start { result in
optimizely.start { result in
switch result {
case .failure(let error):
print("Optimizely SDK initiliazation failed: \(error)")
Expand Down Expand Up @@ -151,7 +151,10 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
}
}
})


_ = optimizely.notificationCenter.addLogEventNotificationListener(logEventListener: { (url, event) in
print("Received logEvent notification: \(url) \(event)")
})
}

// MARK: - ViewControl
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
codeCoverageEnabled = "YES"
Copy link
Contributor

Choose a reason for hiding this comment

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

Why is this in this PR?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It was a part of fixing coverage failure for this PR. I'll try to split into separate one next time :)

shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
<TestableReference
Expand Down
6 changes: 4 additions & 2 deletions Sources/Customization/DefaultEventDispatcher.swift
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,6 @@ open class DefaultEventDispatcher: BackgroundingCallbacks, OPTEventDispatcher {
dataStore: DataStoreUserDefaults())
}


if self.maxQueueSize < self.batchSize {
self.logger.e(.eventDispatcherConfigError("batchSize cannot be bigger than maxQueueSize"))
self.maxQueueSize = self.batchSize
Expand All @@ -93,7 +92,7 @@ open class DefaultEventDispatcher: BackgroundingCallbacks, OPTEventDispatcher {

deinit {
stopTimer()

removeProjectChangeNotificationObservers()

unsubscribe()
Expand Down Expand Up @@ -189,6 +188,9 @@ open class DefaultEventDispatcher: BackgroundingCallbacks, OPTEventDispatcher {
request.httpBody = event.body
request.addValue("application/json", forHTTPHeaderField: "Content-Type")

// send notification BEFORE sending event to the server
NotificationCenter.default.post(name: .willSendOptimizelyEvents, object: event)

let task = session.uploadTask(with: request, from: event.body) { (_, response, error) in
self.logger.d(response.debugDescription)

Expand Down
53 changes: 52 additions & 1 deletion Sources/Implementation/DefaultNotificationCenter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,14 @@ public class DefaultNotificationCenter: OPTNotificationCenter {
public var notificationId: Int = 1
var notificationListeners = [Int: (Int, GenericListener)]()

var observerLogEvent: NSObjectProtocol?

required public init() {

addInternalNotificationListners()
}

deinit {
removeInternalNotificationListners()
}

internal func incrementNotificationId() -> Int {
Expand Down Expand Up @@ -116,6 +122,23 @@ public class DefaultNotificationCenter: OPTNotificationCenter {
return incrementNotificationId()
}

public func addLogEventNotificationListener(logEventListener: @escaping LogEventListener) -> Int? {
notificationListeners[notificationId] = (NotificationType.logEvent.rawValue, { (args: Any...) in
guard let myArgs = args[0] as? [Any?] else {
return
}
if myArgs.count < 2 {
return
}
if let url = myArgs[0] as? String,
let event = myArgs[1] as? [String: Any] {
logEventListener(url, event)
}
})

return incrementNotificationId()
}

public func removeNotificationListener(notificationId: Int) {
self.notificationListeners.removeValue(forKey: notificationId)
}
Expand All @@ -135,3 +158,31 @@ public class DefaultNotificationCenter: OPTNotificationCenter {
}

}

// MARK: Notification Translation

extension DefaultNotificationCenter {

func addInternalNotificationListners() {
observerLogEvent = NotificationCenter.default.addObserver(forName: .willSendOptimizelyEvents, object: nil, queue: nil) { (notif) in
guard let eventForDispatch = notif.object as? EventForDispatch else { return }

let url = eventForDispatch.url.absoluteString
let eventData = eventForDispatch.body

if let event = try? JSONSerialization.jsonObject(with: eventData, options: []) as? [String: Any] {
let args: [Any] = [url, event]
self.sendNotifications(type: NotificationType.logEvent.rawValue, args: args)
} else {
print("LogEvent notification discarded due to invalid event")
}
}
}

func removeInternalNotificationListners() {
if let observer = observerLogEvent {
NotificationCenter.default.removeObserver(observer, name: .willSendOptimizelyEvents, object: nil)
}
}

}
14 changes: 12 additions & 2 deletions Sources/Optimizely/OptimizelyClient+ObjC.swift
Original file line number Diff line number Diff line change
Expand Up @@ -410,6 +410,14 @@ extension OptimizelyClient {
return returnVal(num: num)
}

func addLogEventNotificationListener(logEventListener: @escaping (String, [String: Any]) -> Void) -> NSNumber? {
let num = notifications.addLogEventNotificationListener { (url, event) in
logEventListener(url, event)
}

return returnVal(num: num)
}

func removeNotificationListener(notificationId: Int) {
notifications.removeNotificationListener(notificationId: notificationId)
}
Expand Down Expand Up @@ -441,8 +449,10 @@ extension OptimizelyClient {

let innerEventDispatcher: DefaultEventDispatcher

@objc public init(timerInterval: TimeInterval) {
innerEventDispatcher = DefaultEventDispatcher(timerInterval: timerInterval)
@objc public init(batchSize: Int = DefaultEventDispatcher.DefaultValues.batchSize,
timerInterval: TimeInterval = DefaultEventDispatcher.DefaultValues.timeInterval,
maxQueueSize: Int = DefaultEventDispatcher.DefaultValues.maxQueueSize) {
innerEventDispatcher = DefaultEventDispatcher(batchSize: batchSize, timerInterval: timerInterval, maxQueueSize: maxQueueSize)
}

public func dispatchEvent(event: EventForDispatch, completionHandler: ((Data?, NSError?) -> Void)?) {
Expand Down
Loading