Skip to content

Commit e21373a

Browse files
authored
fix: distinctId and anonymousId should degrade gracefully if they are strings that can't be parsed (#24)
* fix: distinctId and anonymousId should degrade gracefully if they are strings that can't be parsed * format
1 parent e71e616 commit e21373a

File tree

2 files changed

+111
-58
lines changed

2 files changed

+111
-58
lines changed

CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
## Next
22

3+
## 1.0.2 - 2025-02-24
4+
5+
- fix: distinctId and anonymousId should degrade gracefully if they are strings that can't be parsed
6+
37
## 1.0.1 - 2025-02-21
48

59
- chore: pin the iOS SDK to 3.x.x
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.posthogreactnativesessionreplay
22

3+
import android.util.Log
34
import com.facebook.react.bridge.ReactApplicationContext
45
import com.facebook.react.bridge.ReactContextBaseJavaModule
56
import com.facebook.react.bridge.ReactMethod
@@ -25,59 +26,79 @@ class PosthogReactNativeSessionReplayModule(reactContext: ReactApplicationContex
2526
}
2627

2728
@ReactMethod
28-
fun start(sessionId: String, sdkOptions: ReadableMap, sdkReplayConfig: ReadableMap, decideReplayConfig: ReadableMap, promise: Promise) {
29+
fun start(
30+
sessionId: String,
31+
sdkOptions: ReadableMap,
32+
sdkReplayConfig: ReadableMap,
33+
decideReplayConfig: ReadableMap,
34+
promise: Promise
35+
) {
2936
val initRunnable = Runnable {
30-
val uuid = UUID.fromString(sessionId)
31-
PostHogSessionManager.setSessionId(uuid)
32-
33-
val context = this.reactApplicationContext
34-
val apiKey = sdkOptions.getString("apiKey") ?: ""
35-
val host = sdkOptions.getString("host") ?: PostHogConfig.DEFAULT_HOST
36-
val debugValue = sdkOptions.getBoolean("debug")
37-
38-
val maskAllTextInputs = sdkReplayConfig.getBoolean("maskAllTextInputs")
39-
val maskAllImages = sdkReplayConfig.getBoolean("maskAllImages")
40-
val captureLog = sdkReplayConfig.getBoolean("captureLog")
41-
val debouncerDelayMs = sdkReplayConfig.getInt("androidDebouncerDelayMs")
42-
43-
val endpoint = decideReplayConfig.getString("endpoint")
44-
45-
val distinctId = sdkOptions.getString("distinctId") ?: ""
46-
val anonymousId = sdkOptions.getString("anonymousId") ?: ""
47-
val theSdkVersion = sdkOptions.getString("sdkVersion")
48-
49-
var theFlushAt = 20
50-
if (sdkOptions.hasKey("flushAt")) {
51-
theFlushAt = sdkOptions.getInt("flushAt")
52-
}
53-
54-
val config = PostHogAndroidConfig(apiKey, host).apply {
55-
debug = debugValue
56-
captureDeepLinks = false
57-
captureApplicationLifecycleEvents = false
58-
captureScreenViews = false
59-
flushAt = theFlushAt
60-
sessionReplay = true
61-
sessionReplayConfig.screenshot = true
62-
sessionReplayConfig.captureLogcat = captureLog
63-
sessionReplayConfig.debouncerDelayMs = debouncerDelayMs.toLong()
64-
sessionReplayConfig.maskAllImages = maskAllImages
65-
sessionReplayConfig.maskAllTextInputs = maskAllTextInputs
66-
67-
if (!endpoint.isNullOrEmpty()) {
68-
snapshotEndpoint = endpoint
37+
try {
38+
val uuid = UUID.fromString(sessionId)
39+
PostHogSessionManager.setSessionId(uuid)
40+
41+
val context = this.reactApplicationContext
42+
val apiKey = sdkOptions.getString("apiKey") ?: ""
43+
val host = sdkOptions.getString("host") ?: PostHogConfig.DEFAULT_HOST
44+
val debugValue = sdkOptions.getBoolean("debug")
45+
46+
val maskAllTextInputs = sdkReplayConfig.getBoolean("maskAllTextInputs")
47+
val maskAllImages = sdkReplayConfig.getBoolean("maskAllImages")
48+
val captureLog = sdkReplayConfig.getBoolean("captureLog")
49+
val debouncerDelayMs = sdkReplayConfig.getInt("androidDebouncerDelayMs")
50+
51+
val endpoint = decideReplayConfig.getString("endpoint")
52+
53+
val distinctId = try {
54+
sdkOptions.getString("distinctId") ?: ""
55+
} catch (e: Throwable) {
56+
logError("parse distinctId", e)
57+
""
58+
}
59+
val anonymousId = try {
60+
sdkOptions.getString("anonymousId") ?: ""
61+
} catch (e: Throwable) {
62+
logError("parse anonymousId", e)
63+
""
6964
}
65+
val theSdkVersion = sdkOptions.getString("sdkVersion")
7066

71-
if (!theSdkVersion.isNullOrEmpty()) {
72-
sdkName = "posthog-react-native"
73-
sdkVersion = theSdkVersion
67+
var theFlushAt = 20
68+
if (sdkOptions.hasKey("flushAt")) {
69+
theFlushAt = sdkOptions.getInt("flushAt")
7470
}
75-
}
76-
PostHogAndroid.setup(context, config)
7771

78-
setIdentify(config.cachePreferences, distinctId, anonymousId)
72+
val config = PostHogAndroidConfig(apiKey, host).apply {
73+
debug = debugValue
74+
captureDeepLinks = false
75+
captureApplicationLifecycleEvents = false
76+
captureScreenViews = false
77+
flushAt = theFlushAt
78+
sessionReplay = true
79+
sessionReplayConfig.screenshot = true
80+
sessionReplayConfig.captureLogcat = captureLog
81+
sessionReplayConfig.debouncerDelayMs = debouncerDelayMs.toLong()
82+
sessionReplayConfig.maskAllImages = maskAllImages
83+
sessionReplayConfig.maskAllTextInputs = maskAllTextInputs
84+
85+
if (!endpoint.isNullOrEmpty()) {
86+
snapshotEndpoint = endpoint
87+
}
88+
89+
if (!theSdkVersion.isNullOrEmpty()) {
90+
sdkName = "posthog-react-native"
91+
sdkVersion = theSdkVersion
92+
}
93+
}
94+
PostHogAndroid.setup(context, config)
7995

80-
promise.resolve(null)
96+
setIdentify(config.cachePreferences, distinctId, anonymousId)
97+
} catch (e: Throwable) {
98+
logError("start", e)
99+
} finally {
100+
promise.resolve(null)
101+
}
81102
}
82103

83104
// forces the SDK to be initialized on the main thread
@@ -90,31 +111,54 @@ class PosthogReactNativeSessionReplayModule(reactContext: ReactApplicationContex
90111

91112
@ReactMethod
92113
fun startSession(sessionId: String, promise: Promise) {
93-
val uuid = UUID.fromString(sessionId)
94-
PostHogSessionManager.setSessionId(uuid)
95-
PostHog.startSession()
96-
promise.resolve(null)
114+
try {
115+
val uuid = UUID.fromString(sessionId)
116+
PostHogSessionManager.setSessionId(uuid)
117+
PostHog.startSession()
118+
} catch (e: Throwable) {
119+
logError("startSession", e)
120+
} finally {
121+
promise.resolve(null)
122+
}
97123
}
98124

99125
@ReactMethod
100126
fun isEnabled(promise: Promise) {
101-
promise.resolve(PostHog.isSessionReplayActive())
127+
try {
128+
promise.resolve(PostHog.isSessionReplayActive())
129+
} catch (e: Throwable) {
130+
logError("isEnabled", e)
131+
promise.resolve(false)
132+
}
102133
}
103134

104135
@ReactMethod
105136
fun endSession(promise: Promise) {
106-
PostHog.endSession()
107-
promise.resolve(null)
137+
try {
138+
PostHog.endSession()
139+
} catch (e: Throwable) {
140+
logError("endSession", e)
141+
} finally {
142+
promise.resolve(null)
143+
}
108144
}
109145

110146
@ReactMethod
111147
fun identify(distinctId: String, anonymousId: String, promise: Promise) {
112-
setIdentify(PostHog.getConfig<PostHogConfig>()?.cachePreferences, distinctId, anonymousId)
113-
114-
promise.resolve(null)
148+
try {
149+
setIdentify(PostHog.getConfig<PostHogConfig>()?.cachePreferences, distinctId, anonymousId)
150+
} catch (e: Throwable) {
151+
logError("identify", e)
152+
} finally {
153+
promise.resolve(null)
154+
}
115155
}
116156

117-
private fun setIdentify(cachePreferences: PostHogPreferences?, distinctId: String, anonymousId: String) {
157+
private fun setIdentify(
158+
cachePreferences: PostHogPreferences?,
159+
distinctId: String,
160+
anonymousId: String
161+
) {
118162
cachePreferences?.let { preferences ->
119163
if (anonymousId.isNotEmpty()) {
120164
preferences.setValue(ANONYMOUS_ID, anonymousId)
@@ -125,7 +169,12 @@ class PosthogReactNativeSessionReplayModule(reactContext: ReactApplicationContex
125169
}
126170
}
127171

172+
private fun logError(method: String, error: Throwable) {
173+
Log.println(Log.ERROR, POSTHOG_TAG, "Method $method, error: $error")
174+
}
175+
128176
companion object {
129177
const val NAME = "PosthogReactNativeSessionReplay"
178+
const val POSTHOG_TAG = "PostHog"
130179
}
131180
}

0 commit comments

Comments
 (0)