Skip to content

Commit 3643518

Browse files
refactor: for session_id
1 parent e0d5a4b commit 3643518

1 file changed

Lines changed: 92 additions & 200 deletions

File tree

Lines changed: 92 additions & 200 deletions
Original file line numberDiff line numberDiff line change
@@ -1,123 +1,3 @@
1-
// import {
2-
// EventPlugin,
3-
// EventType,
4-
// IdentifyEventType,
5-
// PluginType,
6-
// SegmentAPISettings,
7-
// SegmentEvent,
8-
// TrackEventType,
9-
// ScreenEventType,
10-
// GroupEventType,
11-
// UpdateType,
12-
// AliasEventType,
13-
// SegmentClient,
14-
// } from '@segment/analytics-react-native';
15-
16-
// const MAX_SESSION_TIME_IN_MS = 300000;
17-
// export class AmplitudeSessionPlugin extends EventPlugin {
18-
// type = PluginType.enrichment;
19-
// key = 'Actions Amplitude';
20-
// active = false;
21-
// sessionId: number | undefined;
22-
// sessionTimer: ReturnType<typeof setTimeout> | undefined;
23-
24-
// configure(_analytics: SegmentClient): void {
25-
// this.analytics = _analytics;
26-
// }
27-
28-
// update(settings: SegmentAPISettings, _: UpdateType) {
29-
// const integrations = settings.integrations;
30-
// if (this.key in integrations) {
31-
// this.active = true;
32-
// this.refreshSession();
33-
// }
34-
// }
35-
36-
// execute(event: SegmentEvent) {
37-
// if (!this.active) {
38-
// return event;
39-
// }
40-
41-
// this.refreshSession();
42-
43-
// let result = event;
44-
// switch (result.type) {
45-
// case EventType.IdentifyEvent:
46-
// result = this.identify(result);
47-
// break;
48-
// case EventType.TrackEvent:
49-
// result = this.track(result);
50-
// break;
51-
// case EventType.ScreenEvent:
52-
// result = this.screen(result);
53-
// break;
54-
// case EventType.AliasEvent:
55-
// result = this.alias(result);
56-
// break;
57-
// case EventType.GroupEvent:
58-
// result = this.group(result);
59-
// break;
60-
// }
61-
// return result;
62-
// }
63-
64-
// identify(event: IdentifyEventType) {
65-
// return this.insertSession(event) as IdentifyEventType;
66-
// }
67-
68-
// track(event: TrackEventType) {
69-
// return this.insertSession(event) as TrackEventType;
70-
// }
71-
72-
// screen(event: ScreenEventType) {
73-
// return this.insertSession(event) as ScreenEventType;
74-
// }
75-
76-
// group(event: GroupEventType) {
77-
// return this.insertSession(event) as GroupEventType;
78-
// }
79-
80-
// alias(event: AliasEventType) {
81-
// return this.insertSession(event) as AliasEventType;
82-
// }
83-
84-
// reset() {
85-
// this.resetSession();
86-
// }
87-
88-
// private insertSession = (event: SegmentEvent) => {
89-
// const returnEvent = event;
90-
// const integrations = event.integrations;
91-
// returnEvent.integrations = {
92-
// ...integrations,
93-
// [this.key]: {
94-
// session_id: this.sessionId,
95-
// },
96-
// };
97-
// return returnEvent;
98-
// };
99-
100-
// private resetSession = () => {
101-
// this.sessionId = Date.now();
102-
// this.sessionTimer = undefined;
103-
// };
104-
105-
// private refreshSession = () => {
106-
// if (this.sessionId === undefined) {
107-
// this.sessionId = Date.now();
108-
// }
109-
110-
// if (this.sessionTimer !== undefined) {
111-
// clearTimeout(this.sessionTimer);
112-
// }
113-
114-
// this.sessionTimer = setTimeout(
115-
// () => this.resetSession(),
116-
// MAX_SESSION_TIME_IN_MS
117-
// );
118-
// };
119-
// }
120-
1211
import {
1222
EventPlugin,
1233
EventType,
@@ -135,43 +15,51 @@ import {
13515

13616
import AsyncStorage from '@react-native-async-storage/async-storage';
13717
import { AppState } from 'react-native';
18+
//import { AppState } from 'react-native';
13819

13920
const MAX_SESSION_TIME_IN_MS = 300000;
140-
const SESSION_ID_KEY = 'amplitude_session_id';
141-
const LAST_EVENT_TIME_KEY = 'amplitude_last_event_time';
21+
const SESSION_ID_KEY = 'previous_session_id';
22+
const LAST_EVENT_TIME_KEY = 'last_event_time';
23+
const AMP_SESSION_START_EVENT = 'session_start';
24+
const AMP_SESSION_END_EVENT = 'session_end';
14225

14326
export class AmplitudeSessionPlugin extends EventPlugin {
14427
type = PluginType.enrichment;
14528
key = 'Actions Amplitude';
14629
active = false;
147-
sessionId: number | undefined;
148-
lastEventTime: number | undefined;
30+
sessionId = -1;
31+
lastEventTime = -1;
14932
sessionTimer: ReturnType<typeof setTimeout> | undefined;
15033

151-
configure(_analytics: SegmentClient): void {
152-
this.analytics = _analytics;
34+
configure(analytics: SegmentClient): void {
35+
this.analytics = analytics;
15336
AppState.addEventListener('change', this.handleAppStateChange);
15437
this.loadSessionData();
38+
if (this.sessionId === -1) {
39+
this.startNewSession();
40+
} else {
41+
this.startNewSessionIfNecessary();
42+
}
15543
}
15644

157-
// Called when plugin is initialized with Segment settings
158-
update(settings: SegmentAPISettings, _: UpdateType) {
159-
const integrations = settings.integrations;
160-
if (this.key in integrations) {
161-
this.active = true;
162-
this.refreshSession();
45+
update(settings: SegmentAPISettings, type: UpdateType) {
46+
if (type !== UpdateType.initial) {
47+
return;
16348
}
49+
this.active = settings.integrations?.hasOwnProperty(this.key) ?? false;
16450
}
16551

166-
// Core event processing hook
16752
async execute(event: SegmentEvent) {
16853
if (!this.active) {
16954
return event;
17055
}
171-
172-
await this.refreshSession();
56+
await this.startNewSessionIfNecessary();
17357

17458
let result = event;
59+
if (result.type === EventType.TrackEvent) {
60+
console.log(result.event);
61+
}
62+
17563
switch (result.type) {
17664
case EventType.IdentifyEvent:
17765
result = this.identify(result);
@@ -189,6 +77,10 @@ export class AmplitudeSessionPlugin extends EventPlugin {
18977
result = this.group(result);
19078
break;
19179
}
80+
81+
this.lastEventTime = Date.now();
82+
await this.saveSessionData();
83+
19284
return result;
19385
}
19486

@@ -201,6 +93,10 @@ export class AmplitudeSessionPlugin extends EventPlugin {
20193
}
20294

20395
screen(event: ScreenEventType) {
96+
event.properties = {
97+
...event.properties,
98+
name: event.name,
99+
};
204100
return this.insertSession(event) as ScreenEventType;
205101
}
206102

@@ -213,103 +109,99 @@ export class AmplitudeSessionPlugin extends EventPlugin {
213109
}
214110

215111
reset() {
216-
this.resetSession();
112+
//this.resetSession();
217113
}
218114

219-
// Injects session_id into event's integrations
220115
private insertSession = (event: SegmentEvent) => {
221116
const returnEvent = event;
117+
const integrations = event.integrations || {};
118+
const existingIntegration = integrations[this.key];
119+
const hasSessionId =
120+
typeof existingIntegration === 'object' &&
121+
existingIntegration !== null &&
122+
'session_id' in existingIntegration;
123+
124+
// If session_id exists, return as is
125+
if (hasSessionId) {
126+
return returnEvent;
127+
}
128+
222129
returnEvent.integrations = {
223-
...event.integrations,
130+
...integrations,
224131
[this.key]: {
225132
session_id: this.sessionId,
226133
},
227134
};
228135
return returnEvent;
229136
};
230137

231-
// Emits session start/end events manually (optional for debugging or analytics)
232-
private trackSessionEvent = (eventName: string) => {
233-
if (this.analytics && this.sessionId != null) {
234-
this.analytics.track(eventName, {
138+
private onBackground() {
139+
this.lastEventTime = Date.now();
140+
141+
this.saveSessionData();
142+
}
143+
144+
private onForeground() {
145+
this.startNewSessionIfNecessary();
146+
}
147+
148+
private async startNewSessionIfNecessary() {
149+
const current = Date.now();
150+
const withinSessionLimit =
151+
current - this.lastEventTime < MAX_SESSION_TIME_IN_MS;
152+
if (this.sessionId >= 0 && withinSessionLimit) {
153+
return;
154+
}
155+
this.lastEventTime = current;
156+
await this.endSession();
157+
await this.startNewSession();
158+
}
159+
160+
private async startNewSession() {
161+
this.sessionId = Date.now();
162+
const copy = this.sessionId;
163+
if (this.analytics) {
164+
this.analytics.track(AMP_SESSION_START_EVENT, {
235165
integrations: {
236-
[this.key]: {
237-
session_id: this.sessionId,
238-
},
166+
[this.key]: { session_id: copy },
239167
},
240168
});
241169
}
242-
};
243-
244-
// Creates new session and tracks it
245-
private resetSession = async () => {
246-
this.trackSessionEvent('session_end');
247-
this.sessionId = Date.now();
248-
this.lastEventTime = this.sessionId;
249-
this.trackSessionEvent('session_start');
250-
this.sessionTimer = undefined;
251170
await this.saveSessionData();
252-
};
253-
254-
// Refreshes session only if session timeout occurred
255-
private refreshSession = async () => {
256-
const now = Date.now();
257-
console.log('sessionId', this.sessionId);
258-
console.log('this.lastEventTime', this.lastEventTime);
259-
if (this.lastEventTime != null) {
260-
console.log(
261-
'now - this.lastEventTime > MAX_SESSION_TIME_IN_MS',
262-
now - this.lastEventTime > MAX_SESSION_TIME_IN_MS
263-
);
264-
}
265-
if (
266-
this.sessionId === undefined ||
267-
this.lastEventTime === undefined ||
268-
now - this.lastEventTime > MAX_SESSION_TIME_IN_MS
269-
) {
270-
console.log(' await this.resetSession()');
271-
await this.resetSession();
272-
} else {
273-
this.lastEventTime = now;
274-
console.log(' await this.saveSessionData()');
275-
await this.saveSessionData();
276-
}
171+
}
277172

278-
if (this.sessionTimer !== undefined) {
279-
clearTimeout(this.sessionTimer);
173+
private async endSession() {
174+
const copy = this.sessionId;
175+
if (this.analytics) {
176+
this.analytics.track(AMP_SESSION_END_EVENT, {
177+
integrations: {
178+
[this.key]: { session_id: copy },
179+
},
180+
});
280181
}
182+
}
281183

282-
this.sessionTimer = setTimeout(
283-
() => this.resetSession(),
284-
MAX_SESSION_TIME_IN_MS
285-
);
286-
};
287-
288-
// Loads stored session state from persistent storage
289184
private async loadSessionData() {
290185
const storedSessionId = await AsyncStorage.getItem(SESSION_ID_KEY);
291186
const storedLastEventTime = await AsyncStorage.getItem(LAST_EVENT_TIME_KEY);
292-
this.sessionId =
293-
storedSessionId != null ? Number(storedSessionId) : undefined;
187+
this.sessionId = storedSessionId != null ? Number(storedSessionId) : -1;
294188
this.lastEventTime =
295-
storedLastEventTime != null ? Number(storedLastEventTime) : undefined;
189+
storedLastEventTime != null ? Number(storedLastEventTime) : -1;
296190
}
297191

298-
// Persists session state
299192
private async saveSessionData() {
300-
if (this.sessionId !== undefined) {
301-
await AsyncStorage.setItem(SESSION_ID_KEY, this.sessionId.toString());
302-
await AsyncStorage.setItem(LAST_EVENT_TIME_KEY, Date.now().toString());
303-
}
193+
await AsyncStorage.setItem(SESSION_ID_KEY, this.sessionId.toString());
194+
await AsyncStorage.setItem(
195+
LAST_EVENT_TIME_KEY,
196+
this.lastEventTime.toString()
197+
);
304198
}
305199

306-
// Handles app going to foreground/background
307200
private handleAppStateChange = (nextAppState: string) => {
308-
console.log('nextAppState', nextAppState);
309201
if (nextAppState === 'active') {
310-
this.refreshSession();
202+
this.onForeground();
311203
} else if (nextAppState === 'background') {
312-
this.saveSessionData();
204+
this.onBackground();
313205
}
314206
};
315207
}

0 commit comments

Comments
 (0)