@rejourneyco/react-native 1.0.15 → 1.0.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/android/src/main/java/com/rejourney/RejourneyModuleImpl.kt +2 -0
- package/android/src/main/java/com/rejourney/recording/ReplayOrchestrator.kt +11 -13
- package/android/src/main/java/com/rejourney/recording/SegmentDispatcher.kt +3 -33
- package/android/src/main/java/com/rejourney/recording/TelemetryPipeline.kt +2 -0
- package/ios/Engine/RejourneyImpl.swift +1 -0
- package/ios/Recording/ReplayOrchestrator.swift +11 -14
- package/ios/Recording/SegmentDispatcher.swift +7 -35
- package/ios/Recording/TelemetryPipeline.swift +1 -0
- package/package.json +1 -1
|
@@ -44,6 +44,7 @@ import com.facebook.react.modules.network.NetworkingModule
|
|
|
44
44
|
import okhttp3.OkHttpClient
|
|
45
45
|
import com.rejourney.engine.DeviceRegistrar
|
|
46
46
|
import com.rejourney.engine.DiagnosticLog
|
|
47
|
+
import com.rejourney.engine.RejourneyImpl
|
|
47
48
|
|
|
48
49
|
import com.rejourney.platform.OEMDetector
|
|
49
50
|
import com.rejourney.platform.SessionLifecycleService
|
|
@@ -856,6 +857,7 @@ class RejourneyModuleImpl(
|
|
|
856
857
|
|
|
857
858
|
fun setSDKVersion(version: String) {
|
|
858
859
|
sdkVersion = version
|
|
860
|
+
RejourneyImpl.sdkVersion = version
|
|
859
861
|
}
|
|
860
862
|
|
|
861
863
|
fun getSDKVersion(promise: Promise) {
|
|
@@ -302,19 +302,17 @@ class ReplayOrchestrator private constructor(private val context: Context) {
|
|
|
302
302
|
}
|
|
303
303
|
finalized = true
|
|
304
304
|
|
|
305
|
-
SegmentDispatcher.shared.
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
completion?.invoke(true, ok)
|
|
317
|
-
}
|
|
305
|
+
SegmentDispatcher.shared.concludeReplay(
|
|
306
|
+
sid,
|
|
307
|
+
termMs,
|
|
308
|
+
bgTimeMs,
|
|
309
|
+
metrics,
|
|
310
|
+
queueDepthAtFinalize,
|
|
311
|
+
endReason = endReason,
|
|
312
|
+
lifecycleVersion = lifecycleContractVersion
|
|
313
|
+
) { ok ->
|
|
314
|
+
if (ok) clearRecovery()
|
|
315
|
+
completion?.invoke(true, ok)
|
|
318
316
|
}
|
|
319
317
|
|
|
320
318
|
replayId = null
|
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
package com.rejourney.recording
|
|
18
18
|
|
|
19
19
|
import com.rejourney.engine.DiagnosticLog
|
|
20
|
+
import com.rejourney.engine.RejourneyImpl
|
|
20
21
|
import kotlinx.coroutines.*
|
|
21
22
|
import okhttp3.*
|
|
22
23
|
import com.rejourney.recording.RejourneyNetworkInterceptor
|
|
@@ -285,6 +286,7 @@ class SegmentDispatcher private constructor() {
|
|
|
285
286
|
val body = JSONObject().apply {
|
|
286
287
|
put("sessionId", replayId)
|
|
287
288
|
put("endedAt", concludedAt)
|
|
289
|
+
put("sdkVersion", RejourneyImpl.sdkVersion)
|
|
288
290
|
if (backgroundDurationMs > 0) put("totalBackgroundTimeMs", backgroundDurationMs)
|
|
289
291
|
metrics?.let { put("metrics", JSONObject(it)) }
|
|
290
292
|
put("sdkTelemetry", buildSdkTelemetry(currentQueueDepth))
|
|
@@ -304,39 +306,6 @@ class SegmentDispatcher private constructor() {
|
|
|
304
306
|
}
|
|
305
307
|
}
|
|
306
308
|
|
|
307
|
-
fun evaluateReplayRetention(
|
|
308
|
-
replayId: String,
|
|
309
|
-
metrics: Map<String, Any>,
|
|
310
|
-
completion: (Boolean, String) -> Unit
|
|
311
|
-
) {
|
|
312
|
-
val url = "$endpoint/api/ingest/replay/evaluate"
|
|
313
|
-
|
|
314
|
-
val body = JSONObject().apply {
|
|
315
|
-
put("sessionId", replayId)
|
|
316
|
-
metrics.forEach { (key, value) -> put(key, value) }
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
val request = buildRequest(url, body)
|
|
320
|
-
|
|
321
|
-
scope.launch {
|
|
322
|
-
try {
|
|
323
|
-
val response = httpClient.newCall(request).execute()
|
|
324
|
-
val responseBody = response.body?.string()
|
|
325
|
-
|
|
326
|
-
if (response.code == 200 && responseBody != null) {
|
|
327
|
-
val json = JSONObject(responseBody)
|
|
328
|
-
val retained = json.optBoolean("promoted", false)
|
|
329
|
-
val reason = json.optString("reason", "unknown")
|
|
330
|
-
completion(retained, reason)
|
|
331
|
-
} else {
|
|
332
|
-
completion(false, "request_failed")
|
|
333
|
-
}
|
|
334
|
-
} catch (e: Exception) {
|
|
335
|
-
completion(false, "request_failed")
|
|
336
|
-
}
|
|
337
|
-
}
|
|
338
|
-
}
|
|
339
|
-
|
|
340
309
|
@Synchronized
|
|
341
310
|
private fun canUploadNow(): Boolean {
|
|
342
311
|
if (billingBlocked) return false
|
|
@@ -461,6 +430,7 @@ class SegmentDispatcher private constructor() {
|
|
|
461
430
|
val body = JSONObject().apply {
|
|
462
431
|
put("sessionId", upload.sessionId)
|
|
463
432
|
put("sizeBytes", upload.payload.size)
|
|
433
|
+
put("sdkVersion", RejourneyImpl.sdkVersion)
|
|
464
434
|
|
|
465
435
|
if (upload.contentType == "events") {
|
|
466
436
|
put("contentType", "events")
|
|
@@ -22,6 +22,7 @@ import android.os.Handler
|
|
|
22
22
|
import android.os.Looper
|
|
23
23
|
import com.rejourney.engine.DiagnosticLog
|
|
24
24
|
import com.rejourney.engine.DeviceRegistrar
|
|
25
|
+
import com.rejourney.engine.RejourneyImpl
|
|
25
26
|
import com.rejourney.utility.gzipCompress
|
|
26
27
|
import org.json.JSONArray
|
|
27
28
|
import org.json.JSONObject
|
|
@@ -340,6 +341,7 @@ class TelemetryPipeline private constructor(private val context: Context) {
|
|
|
340
341
|
put("isConstrained", orchestrator?.networkIsConstrained ?: false)
|
|
341
342
|
put("isExpensive", orchestrator?.networkIsExpensive ?: false)
|
|
342
343
|
put("appVersion", getAppVersion())
|
|
344
|
+
put("sdkVersion", RejourneyImpl.sdkVersion)
|
|
343
345
|
put("appId", context.packageName)
|
|
344
346
|
put("screenWidth", displayMetrics.widthPixels)
|
|
345
347
|
put("screenHeight", displayMetrics.heightPixels)
|
|
@@ -78,6 +78,7 @@ public final class RejourneyImpl: NSObject {
|
|
|
78
78
|
NotificationCenter.default.removeObserver(self)
|
|
79
79
|
}
|
|
80
80
|
|
|
81
|
+
//NOTE: iOS cannot detect reliably app kill so we depend server side with the session reconciliation logic
|
|
81
82
|
private func setupLifecycleListeners() {
|
|
82
83
|
let center = NotificationCenter.default
|
|
83
84
|
center.addObserver(self, selector: #selector(handleTermination), name: UIApplication.willTerminateNotification, object: nil)
|
|
@@ -258,20 +258,17 @@ public final class ReplayOrchestrator: NSObject {
|
|
|
258
258
|
}
|
|
259
259
|
_finalized = true
|
|
260
260
|
|
|
261
|
-
SegmentDispatcher.shared.
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
if ok { self?._clearRecovery() }
|
|
273
|
-
completion?(true, ok)
|
|
274
|
-
}
|
|
261
|
+
SegmentDispatcher.shared.concludeReplay(
|
|
262
|
+
replayId: sid,
|
|
263
|
+
concludedAt: termMs,
|
|
264
|
+
backgroundDurationMs: _bgTimeMs,
|
|
265
|
+
metrics: metrics,
|
|
266
|
+
currentQueueDepth: queueDepthAtFinalize,
|
|
267
|
+
endReason: endReason,
|
|
268
|
+
lifecycleVersion: lifecycleContractVersion
|
|
269
|
+
) { [weak self] ok in
|
|
270
|
+
if ok { self?._clearRecovery() }
|
|
271
|
+
completion?(true, ok)
|
|
275
272
|
}
|
|
276
273
|
|
|
277
274
|
replayId = nil
|
|
@@ -195,7 +195,11 @@ final class SegmentDispatcher {
|
|
|
195
195
|
req.setValue("application/json", forHTTPHeaderField: "Content-Type")
|
|
196
196
|
applyAuthHeaders(&req)
|
|
197
197
|
|
|
198
|
-
var body: [String: Any] = [
|
|
198
|
+
var body: [String: Any] = [
|
|
199
|
+
"sessionId": replayId,
|
|
200
|
+
"endedAt": concludedAt,
|
|
201
|
+
"sdkVersion": RejourneyImpl.sdkVersion
|
|
202
|
+
]
|
|
199
203
|
if backgroundDurationMs > 0 { body["totalBackgroundTimeMs"] = backgroundDurationMs }
|
|
200
204
|
if let m = metrics { body["metrics"] = m }
|
|
201
205
|
body["sdkTelemetry"] = sdkTelemetrySnapshot(currentQueueDepth: currentQueueDepth)
|
|
@@ -218,39 +222,6 @@ final class SegmentDispatcher {
|
|
|
218
222
|
}.resume()
|
|
219
223
|
}
|
|
220
224
|
|
|
221
|
-
func evaluateReplayRetention(replayId: String, metrics: [String: Any], completion: @escaping (Bool, String) -> Void) {
|
|
222
|
-
guard let url = URL(string: "\(endpoint)/api/ingest/replay/evaluate") else {
|
|
223
|
-
completion(false, "bad_url")
|
|
224
|
-
return
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
var req = URLRequest(url: url)
|
|
228
|
-
req.httpMethod = "POST"
|
|
229
|
-
req.setValue("application/json", forHTTPHeaderField: "Content-Type")
|
|
230
|
-
applyAuthHeaders(&req)
|
|
231
|
-
|
|
232
|
-
var body: [String: Any] = ["sessionId": replayId]
|
|
233
|
-
metrics.forEach { body[$0.key] = $0.value }
|
|
234
|
-
|
|
235
|
-
do {
|
|
236
|
-
req.httpBody = try JSONSerialization.data(withJSONObject: body)
|
|
237
|
-
} catch {
|
|
238
|
-
completion(false, "serialize_error")
|
|
239
|
-
return
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
httpSession.dataTask(with: req) { data, resp, _ in
|
|
243
|
-
guard let data, (resp as? HTTPURLResponse)?.statusCode == 200,
|
|
244
|
-
let json = try? JSONSerialization.jsonObject(with: data) as? [String: Any] else {
|
|
245
|
-
completion(false, "request_failed")
|
|
246
|
-
return
|
|
247
|
-
}
|
|
248
|
-
let retained = json["promoted"] as? Bool ?? false
|
|
249
|
-
let reason = json["reason"] as? String ?? "unknown"
|
|
250
|
-
completion(retained, reason)
|
|
251
|
-
}.resume()
|
|
252
|
-
}
|
|
253
|
-
|
|
254
225
|
private func canUploadNow() -> Bool {
|
|
255
226
|
if billingBlocked { return false }
|
|
256
227
|
if circuitOpen {
|
|
@@ -382,7 +353,8 @@ final class SegmentDispatcher {
|
|
|
382
353
|
|
|
383
354
|
var body: [String: Any] = [
|
|
384
355
|
"sessionId": upload.sessionId,
|
|
385
|
-
"sizeBytes": upload.payload.count
|
|
356
|
+
"sizeBytes": upload.payload.count,
|
|
357
|
+
"sdkVersion": RejourneyImpl.sdkVersion
|
|
386
358
|
]
|
|
387
359
|
|
|
388
360
|
if upload.contentType == "events" {
|
|
@@ -354,6 +354,7 @@ public final class TelemetryPipeline: NSObject {
|
|
|
354
354
|
"isConstrained": isConstrained,
|
|
355
355
|
"isExpensive": isExpensive,
|
|
356
356
|
"appVersion": appVersion,
|
|
357
|
+
"sdkVersion": RejourneyImpl.sdkVersion,
|
|
357
358
|
"appId": appId,
|
|
358
359
|
"screenWidth": Int(bounds.width),
|
|
359
360
|
"screenHeight": Int(bounds.height),
|