Skip to content

Commit

Permalink
Feature/health tracking (#4)
Browse files Browse the repository at this point in the history
* Health tracking

* Added Clickstream Health Tracking

* Added verbosity level for health tracking

* Added tracker DTO and handle verbosity level

* Added Tracker.md file

* Minor code changes and resolve PR comments

* Fixed PR comments

* Skip table migration

* Improvements in Health tracking.

* Fixed PR suggestions.

* Minor fix

* Added comments
  • Loading branch information
AbhijeetMallick authored Jun 28, 2022
1 parent b4c9046 commit 658b35a
Show file tree
Hide file tree
Showing 40 changed files with 2,501 additions and 91 deletions.
10 changes: 10 additions & 0 deletions Clickstream.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -30,5 +30,15 @@ Pod::Spec.new do |s|
s.dependency "ReachabilitySwift"
s.dependency "GRDB.swift", "5.12.0"
s.dependency "Starscream", "4.0.4"
s.default_subspec = 'Core'

s.subspec 'Core' do |core|
end

s.subspec 'Tracker' do |tracker|
tracker.source_files = 'Tracker/**/*.swift'
tracker.xcconfig = { 'SWIFT_ACTIVE_COMPILATION_CONDITIONS' => '$(inherited) TRACKER_ENABLED' }
end


end
133 changes: 123 additions & 10 deletions Clickstream.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

13 changes: 13 additions & 0 deletions Clickstream.xcworkspace/contents.xcworkspacedata

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions Clickstream.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>
5 changes: 1 addition & 4 deletions Clickstream/Core/Data/Constants/Constants.swift
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,7 @@ enum Constants {
case dao = "com.clickstream.dao"
case connectableAccess = "com.clickstream.connectableAccess"
case atomicAccess = "com.clickstream.atomicAccess"
}

enum CacheIdentifiers: CacheIdentifier {
case retry = "com.clickstream.retryCache"
case tracker = "com.gojek.clickstream.tracker"
}

enum EventType: String, Codable {
Expand Down
4 changes: 0 additions & 4 deletions Clickstream/Core/Domain/Entities/Event.swift
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,6 @@ extension Event: DatabasePersistable {
}
}

static var codableCacheKey: String {
return "realTime"
}

static var primaryKey: String {
return "guid"
}
Expand Down
29 changes: 23 additions & 6 deletions Clickstream/Core/Interface/ClickStream.swift
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,6 @@ public final class Clickstream {
/// Temporary handling. Will be replaced by an experimentation module within Clickstream.
internal static var isInitialisedOnBackgroundQueue: Bool = false

/// Tells whether the debugMode is enabled or not.
internal static var debugMode: Bool = false

/// Holds the constraints for the sdk.
internal static var constraints: ClickstreamConstraints = ClickstreamConstraints()

Expand Down Expand Up @@ -89,9 +86,6 @@ public final class Clickstream {
public func trackEvent(with event: ClickstreamEvent) {
self.eventProcessor.createEvent(event: event)
}
}

extension Clickstream {

/// Initializes an instance of the API with the given configurations.
/// Returns a new Clickstream instance API object. This allows you to create one instance only.
Expand Down Expand Up @@ -145,3 +139,26 @@ extension Clickstream {
return sharedInstance
}
}

// MARK: - Code below here is support for the Clickstream's Health Tracking.
#if TRACKER_ENABLED
extension Clickstream {

/// Initialise tracker
/// - Parameters:
/// - configs: ClickstreamHealthConfigurations
/// - commonProperties: CSCommonProperties
/// - dataSource: TrackerDataSource
/// - delegate: TrackerDelegate
public func setTracker(configs: ClickstreamHealthConfigurations,
commonProperties: CSCommonProperties,
dataSource: TrackerDataSource,
delegate: TrackerDelegate) {
Tracker.initialise(commonProperties: commonProperties, healthTrackingConfigs: configs,dataSource: dataSource, delegate: delegate)
}

public func getTracker() -> Tracker? {
return Tracker.sharedInstance
}
}
#endif
30 changes: 26 additions & 4 deletions Clickstream/EventProcessor/Core/EventProcessor.swift
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,15 @@ final class DefaultEventProcessor: EventProcessor {
// Create an Event instance and forward it to the scheduler.
if let event = checkedSelf.constructEvent(event: event) {
checkedSelf.eventWarehouser.store(event)
#if TRACKER_ENABLED
if Tracker.debugMode {
let healthEvent = HealthAnalysisEvent(eventName: .ClickstreamEventReceived,
eventGUID: event.guid)
if event.type != Constants.EventType.instant.rawValue {
Tracker.sharedInstance?.record(event: healthEvent)
}
}
#endif
}
}
}
Expand All @@ -47,17 +56,30 @@ final class DefaultEventProcessor: EventProcessor {
guard let classification = classifier.getClassification(eventName: type(of: event.message).protoMessageName) else {
return nil
}


#if TRACKER_ENABLED
if Tracker.debugMode && classification != Constants.EventType.instant.rawValue {
var _eventGuid = event.guid
if !Tracker.healthTrackingConfigs.dropRateEventName.isEmpty {
_eventGuid = event.guid.appending("_\(Tracker.healthTrackingConfigs.dropRateEventName)")
} else {
_eventGuid = event.guid.appending("_\(typeOfEvent)")
}
let healthEvent = HealthAnalysisEvent(eventName: .ClickstreamEventReceivedForDropRate, eventGUID: _eventGuid)
Tracker.sharedInstance?.record(event: healthEvent)
}
#endif

do {
// Constructing the Odpf_Raccoon_Event
let csEvent = try Odpf_Raccoon_Event.with {
$0.eventBytes = try event.message.serializedData()
$0.type = typeOfEvent
}
return try Event(guid: event.guid,
timestamp: event.timeStamp,
type: classification,
eventProtoData: csEvent.serializedData())
timestamp: event.timeStamp,
type: classification,
eventProtoData: csEvent.serializedData())
} catch {
return nil
}
Expand Down
20 changes: 19 additions & 1 deletion Clickstream/EventScheduler/Core/EventBatchCreator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,9 @@ extension DefaultEventBatchCreator {
func forward(with events: [Event]) -> Bool {
if canForward {
let batch = EventBatch(uuid: UUID().uuidString, events: events)

networkBuilder.trackBatch(batch, completion: nil)

self.trackHealthEvents(batch: batch, events: events)
return true
}
return false
Expand All @@ -69,3 +70,20 @@ extension DefaultEventBatchCreator {
networkBuilder.isAvailable
}
}

// MARK: - Track Clickstream health.
extension DefaultEventBatchCreator {
private func trackHealthEvents(batch: EventBatch, events: [Event]) {
#if TRACKER_ENABLED
// We are checking only first event's type since batches are created on the basis of evemt priority i.e. realTime, healthEvent etc.
if events.first?.type != TrackerConstant.HealthEventType && events.first?.type != Constants.EventType.instant.rawValue {
let eventGUIDs = batch.events.map { $0.guid }
let eventGUIDString = "\(eventGUIDs.joined(separator: ", "))"
let batchCreatedEvent = HealthAnalysisEvent(eventName: .ClickstreamEventBatchCreated,
events: eventGUIDString,
eventBatchGUID: batch.uuid)
Tracker.sharedInstance?.record(event: batchCreatedEvent)
}
#endif
}
}
22 changes: 22 additions & 0 deletions Clickstream/EventScheduler/Core/EventBatchProcessor.swift
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ final class DefaultEventBatchProcessor: EventBatchProcessor {
switch stateNotification {
case .willTerminate, .didEnterBackground:
checkedSelf.flushAll()
checkedSelf.flushObservabilityEvents()
case .willResignActive:
checkedSelf.stopTimer()
case .didBecomeActive:
Expand Down Expand Up @@ -136,6 +137,15 @@ final class DefaultEventBatchProcessor: EventBatchProcessor {

if !eventsToBeFlushed.isEmpty {
eventBatchCreator.forward(with: eventsToBeFlushed)
#if TRACKER_ENABLED
if Tracker.debugMode {
let eventGUIDs = eventsToBeFlushed.map { $0.guid }
let eventGUIDString = "\(eventGUIDs.joined(separator: ", "))"
let healthAnalysisEvent = HealthAnalysisEvent(eventName: .ClickstreamFlushOnBackground,
events: eventGUIDString)
Tracker.sharedInstance?.record(event: healthAnalysisEvent)
}
#endif
}
}
}
Expand All @@ -156,6 +166,7 @@ final class DefaultEventBatchProcessor: EventBatchProcessor {
let isConnected = object[Constants.Strings.didConnect] as? Bool,
isConnected == true {
flushAll()
flushObservabilityEvents()
}
}

Expand All @@ -170,3 +181,14 @@ final class DefaultEventBatchProcessor: EventBatchProcessor {
eventBatchCreator.stop()
}
}

private extension DefaultEventBatchProcessor {

func flushObservabilityEvents() {
#if TRACKER_ENABLED
if eventBatchCreator.canForward, let events = Tracker.sharedInstance?.sendHealthEventsToInternalParty()(), !events.isEmpty {
eventBatchCreator.forward(with: events)
}
#endif
}
}
8 changes: 8 additions & 0 deletions Clickstream/EventScheduler/Core/EventWarehouser.swift
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,14 @@ extension DefaultEventWarehouser {
} else {
checkedSelf.batchRegulator.observe(event)
checkedSelf.persistence.insert(event)

#if TRACKER_ENABLED
let healthEvent = HealthAnalysisEvent(eventName: .ClickstreamEventCached,
eventGUID: event.guid)
if event.type != Constants.EventType.instant.rawValue {
Tracker.sharedInstance?.record(event: healthEvent)
}
#endif
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,4 @@
import GRDB

/// Any object conforming to this protocol can be persisted on the db.
protocol DatabasePersistable: FetchableRecord, PersistableRecord, TableDefinable, FileStorable {}
protocol DatabasePersistable: FetchableRecord, PersistableRecord, TableDefinable {}
28 changes: 0 additions & 28 deletions Clickstream/EventScheduler/Domain/Protocols/FileStorable.swift

This file was deleted.

19 changes: 19 additions & 0 deletions Clickstream/NetworkManager/Core/NetworkBuilder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,9 @@ extension DefaultNetworkBuilder {

if eventBatch.events.first?.type == Constants.EventType.instant.rawValue {
eventRequest.eventType = .instant
} else {
checkedSelf.trackHealthEvents(eventBatch: eventBatch,
eventBatchData: data)
}

checkedSelf.retryMech.trackBatch(with: eventRequest)
Expand All @@ -85,3 +88,19 @@ extension DefaultNetworkBuilder {
}
}
}

// MARK: - Track Clickstream health.
extension DefaultNetworkBuilder {
private func trackHealthEvents(eventBatch: EventBatch, eventBatchData: Data) {
#if TRACKER_ENABLED
guard Tracker.debugMode else { return }
let eventGUIDs: [String] = eventBatch.events.compactMap { $0.guid }
let eventGUIDsString = "\(eventGUIDs.joined(separator: ", "))"

let healthEvent = HealthAnalysisEvent(eventName: .ClickstreamBatchSent,
events: eventGUIDsString,
eventBatchGUID: eventBatch.uuid)
Tracker.sharedInstance?.record(event: healthEvent)
#endif
}
}
Loading

0 comments on commit 658b35a

Please sign in to comment.