Skip to content

Commit 8dcaa38

Browse files
authored
Fix Screen & Session ID generation/maintenance (#23)
* Forward screen events to amplitude correctly. * Fixes infinite loop * Fixed screen name property value * Another attempt at screen * more session changes * Removed segment disable. * Added flag to debug easier.
1 parent 1f1ba58 commit 8dcaa38

File tree

1 file changed

+78
-27
lines changed

1 file changed

+78
-27
lines changed

Sources/SegmentAmplitude/AmplitudeSession.swift

Lines changed: 78 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -51,20 +51,25 @@ public class AmplitudeSession: EventPlugin, iOSLifecycle {
5151
static let ampAppBackgroundedEvent = "\(ampPrefix)Application Backgrounded"
5252
static let ampDeepLinkOpenedEvent = "\(ampPrefix)Deep Link Opened"
5353
static let ampScreenViewedEvent = "\(ampPrefix)Screen Viewed"
54+
static let ampScreenNameProperty = "\(ampPrefix)Screen Name"
5455
}
5556

57+
public var logging: Bool = false
58+
5659
@Atomic private var active = false
5760
@Atomic private var inForeground: Bool = false
61+
@Atomic private var resetPending: Bool = false
5862
private var storage = Storage()
5963

60-
@Atomic var sessionID: Int64 {
64+
internal var eventSessionID: Int64 = -1
65+
@Atomic internal var sessionID: Int64 {
6166
didSet {
6267
storage.write(key: Storage.Constants.previousSessionID, value: sessionID)
63-
//print("sessionID = \(sessionID)")
68+
debugLog("sessionID set to: \(sessionID)")
6469
}
6570
}
6671

67-
@Atomic var lastEventTime: Int64 {
72+
@Atomic internal var lastEventTime: Int64 {
6873
didSet {
6974
storage.write(key: Storage.Constants.lastEventTime, value: lastEventTime)
7075
}
@@ -73,7 +78,17 @@ public class AmplitudeSession: EventPlugin, iOSLifecycle {
7378
public init() {
7479
self.sessionID = storage.read(key: Storage.Constants.previousSessionID) ?? -1
7580
self.lastEventTime = storage.read(key: Storage.Constants.lastEventTime) ?? -1
76-
//print("startup sessionID = \(sessionID)")
81+
debugLog("startup sessionID = \(sessionID)")
82+
}
83+
84+
public func configure(analytics: Analytics) {
85+
self.analytics = analytics
86+
87+
if sessionID == -1 {
88+
startNewSession()
89+
} else {
90+
startNewSessionIfNecessary()
91+
}
7792
}
7893

7994
public func update(settings: Settings, type: UpdateType) {
@@ -84,34 +99,50 @@ public class AmplitudeSession: EventPlugin, iOSLifecycle {
8499
} else {
85100
active = false
86101
}
87-
88-
if sessionID == -1 {
89-
startNewSession()
90-
} else {
91-
startNewSessionIfNecessary()
92-
}
93102
}
94103

95104
public func execute<T: RawEvent>(event: T?) -> T? {
96105
guard let event else { return nil }
97-
guard let event = defaultEventHandler(event: event) else { return nil }
106+
var workingEvent = defaultEventHandler(event: event)
107+
108+
debugLog("execute called")
109+
110+
// check if time has elapsed and kick of a new session if it has.
111+
// this will send events back through to do the tasks; nothing really happens inline.
112+
startNewSessionIfNecessary()
98113

99-
if var trackEvent = event as? TrackEvent {
114+
// handle screen
115+
if var screenEvent = workingEvent as? ScreenEvent, let screenName = screenEvent.name {
116+
var adjustedProps = screenEvent.properties
117+
// amp needs the `name` in the properties
118+
if adjustedProps == nil {
119+
adjustedProps = try? JSON(["name": screenName])
120+
} else {
121+
adjustedProps?.setValue(screenName, forKeyPath: KeyPath("name"))
122+
}
123+
screenEvent.properties = adjustedProps
124+
workingEvent = screenEvent as? T
125+
}
126+
127+
// handle track
128+
if var trackEvent = workingEvent as? TrackEvent {
100129
let eventName = trackEvent.event
101-
102-
// check if time has elapsed and kick of a new session if it has.
103-
// this will send events back through to do the tasks; nothing really happens inline.
104-
startNewSessionIfNecessary()
105-
130+
106131
// if it's a start event, set a new sessionID
107132
if eventName == Constants.ampSessionStartEvent {
108-
sessionID = newTimestamp()
133+
resetPending = false
134+
eventSessionID = sessionID
135+
debugLog("NewSession = \(eventSessionID)")
136+
}
137+
138+
if eventName == Constants.ampSessionEndEvent {
139+
debugLog("EndSession = \(eventSessionID)")
109140
}
110141

111142
// if it's amp specific stuff, disable all the integrations except for amp.
112143
if eventName.contains(Constants.ampPrefix) || eventName == Constants.ampSessionStartEvent || eventName == Constants.ampSessionEndEvent {
113144
var integrations = disableAllIntegrations(integrations: trackEvent.integrations)
114-
integrations?.setValue(["session_id": sessionID], forKeyPath: KeyPath(key))
145+
integrations?.setValue(["session_id": eventSessionID], forKeyPath: KeyPath(key))
115146
trackEvent.integrations = integrations
116147
}
117148

@@ -137,11 +168,11 @@ public class AmplitudeSession: EventPlugin, iOSLifecycle {
137168
break
138169
}
139170

140-
return trackEvent as? T
171+
workingEvent = trackEvent as? T
141172
}
142173

143174
lastEventTime = newTimestamp()
144-
return event
175+
return workingEvent
145176
}
146177

147178
public func reset() {
@@ -150,12 +181,11 @@ public class AmplitudeSession: EventPlugin, iOSLifecycle {
150181

151182
public func applicationWillEnterForeground(application: UIApplication?) {
152183
startNewSessionIfNecessary()
153-
print("Foreground: \(sessionID)")
154-
analytics?.log(message: "Amplitude Session ID: \(sessionID)")
184+
debugLog("Foreground: \(eventSessionID)")
155185
}
156186

157187
public func applicationWillResignActive(application: UIApplication?) {
158-
print("Background: \(sessionID)")
188+
debugLog("Background: \(eventSessionID)")
159189
lastEventTime = newTimestamp()
160190
}
161191
}
@@ -177,8 +207,6 @@ extension AmplitudeSession {
177207
result?.setValue(false, forKeyPath: KeyPath(key))
178208
}
179209
}
180-
// make sure segment is disabled too.
181-
result?.setValue(false, forKeyPath: KeyPath("Segment.io"))
182210
return result
183211
}
184212

@@ -197,15 +225,31 @@ extension AmplitudeSession {
197225
}
198226

199227
private func startNewSession() {
228+
if resetPending { return }
229+
resetPending = true
230+
sessionID = newTimestamp()
231+
if eventSessionID == -1 {
232+
// we only wanna do this if we had nothing before, so each
233+
// event actually HAS a sessionID of some kind associated.
234+
eventSessionID = sessionID
235+
}
200236
analytics?.track(name: Constants.ampSessionStartEvent)
201237
}
202238

203239
private func startNewSessionIfNecessary() {
240+
if eventSessionID == -1 {
241+
// we only wanna do this if we had nothing before, so each
242+
// event actually HAS a sessionID of some kind associated.
243+
eventSessionID = sessionID
244+
}
245+
246+
if resetPending { return }
204247
let timestamp = newTimestamp()
205248
let withinSessionLimit = withinMinSessionTime(timestamp: timestamp)
206249
if sessionID >= 0 && withinSessionLimit {
207250
return
208251
}
252+
209253
// we'll consider this our new lastEventTime
210254
lastEventTime = timestamp
211255
// end previous session
@@ -221,7 +265,7 @@ extension AmplitudeSession {
221265
private func insertSession(event: RawEvent) -> RawEvent {
222266
var returnEvent = event
223267
if var integrations = event.integrations?.dictionaryValue {
224-
integrations[key] = ["session_id": sessionID]
268+
integrations[key] = ["session_id": eventSessionID]
225269
returnEvent.integrations = try? JSON(integrations as Any)
226270
}
227271
return returnEvent
@@ -236,6 +280,13 @@ extension AmplitudeSession {
236280
let timeDelta = timestamp - self.lastEventTime
237281
return timeDelta < minMilisecondsBetweenSessions
238282
}
283+
284+
private func debugLog(_ str: String) {
285+
if logging {
286+
print("[AmplitudeSession] \(str)")
287+
}
288+
analytics?.log(message: "[AmplitudeSession] \(str)")
289+
}
239290
}
240291

241292
// MARK: - Storage for Session information

0 commit comments

Comments
 (0)