Skip to content

Commit 3a02179

Browse files
committed
Merge branch 'andrey/ld-android2' into andrey/android-internal
* andrey/ld-android2: fix address feedback fix: [SDK-2197] manually register main Activity with session replay (#475) chore: silence otlp localhost connection exceptions in e2e tests (#474) chore: release main (#470)
2 parents 27a04e8 + 6ad6a88 commit 3a02179

10 files changed

Lines changed: 41 additions & 12 deletions

File tree

.release-please-manifest.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
{
22
"go": "1.1.0",
33
"sdk/@launchdarkly/observability": "1.1.2",
4-
"sdk/@launchdarkly/observability-android": "0.38.0",
4+
"sdk/@launchdarkly/observability-android": "0.39.0",
55
"sdk/@launchdarkly/observability-dotnet": "1.1.0",
66
"sdk/@launchdarkly/observability-node": "1.1.0",
77
"sdk/@launchdarkly/observability-python": "1.2.0",
88
"sdk/@launchdarkly/observability-react-native": "0.8.0",
9-
"sdk/@launchdarkly/react-native-ld-session-replay": "0.3.0",
9+
"sdk/@launchdarkly/react-native-ld-session-replay": "0.4.0",
1010
"sdk/@launchdarkly/session-replay": "1.1.2",
1111
"sdk/highlight-run": "10.0.0",
1212
"sdk/@launchdarkly/observability-ruby": "0.2.0"

e2e/android/app/src/main/java/com/example/androidobservability/BaseApplication.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ open class BaseApplication : Application() {
5757

5858
var testUrl: String? = null
5959

60+
// example on creating OBS/SR with flagging sdk
6061
open fun realInit() {
6162
val observabilityPlugin = Observability(
6263
application = this@BaseApplication,
@@ -96,6 +97,7 @@ open class BaseApplication : Application() {
9697
LDReplay.start()
9798
}
9899

100+
// example on creating OBS/SR without flagging
99101
open fun realIndependentInit() {
100102
val effectiveOptions = testUrl?.let {
101103
observabilityOptions.copy(backendUrl = it, otlpEndpoint = it)

e2e/android/app/src/test/java/com/example/androidobservability/SamplingE2ETest.kt

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -64,12 +64,16 @@ class SamplingE2ETest {
6464
@Test
6565
fun `should avoid exporting logs matching sampling configuration for logs`() = runTest {
6666
triggerLogs()
67-
telemetryInspector?.logExporter?.flush()
67+
// Force the BatchLogRecordProcessor to drain everything to the exporter so the
68+
// assertion doesn't race with the batch scheduler.
69+
LDObserve.flush()
6870
waitForTelemetryData(telemetryInspector = application.telemetryInspector, telemetryType = TelemetryType.LOGS)
6971

70-
val logsExported = telemetryInspector?.logExporter?.finishedLogRecordItems?.map {
71-
it.bodyValue?.value.toString()
72-
}
72+
val logsExported = telemetryInspector?.logExporter?.finishedLogRecordItems
73+
?.map { it.bodyValue?.value.toString() }
74+
// The SDK emits an unrelated "LD.identify" INFO log during init; filter it out so
75+
// this test only observes the logs triggered by triggerLogs().
76+
?.filter { it != LD_IDENTIFY_LOG_BODY }
7377

7478
// Only first and final logs should be exported
7579
assertEquals(2, logsExported?.size)
@@ -80,7 +84,7 @@ class SamplingE2ETest {
8084
@Test
8185
fun `should avoid exporting spans matching sampling configuration for spans`() = runTest {
8286
triggerSpans()
83-
telemetryInspector?.spanExporter?.flush()
87+
LDObserve.flush()
8488
waitForTelemetryData(telemetryInspector = application.telemetryInspector, telemetryType = TelemetryType.SPANS)
8589

8690
val spansExported = telemetryInspector?.spanExporter?.finishedSpanItems?.map {
@@ -225,4 +229,8 @@ class SamplingE2ETest {
225229
)
226230
)
227231
}
232+
233+
companion object {
234+
private const val LD_IDENTIFY_LOG_BODY = "LD.identify"
235+
}
228236
}

sdk/@launchdarkly/observability-android/CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
# Changelog
22

3+
## [0.39.0](https://github.com/launchdarkly/observability-sdk/compare/launchdarkly-observability-android-0.38.0...launchdarkly-observability-android-0.39.0) (2026-04-17)
4+
5+
6+
### Features
7+
8+
* [SDK-2197] Add `LDReplay. registerActivity()` method for React Native. ([#472](https://github.com/launchdarkly/observability-sdk/issues/472)) ([f99b566](https://github.com/launchdarkly/observability-sdk/commit/f99b5660f68ac8ec1edf94f27e9eb29dea7c4d93))
9+
310
## [0.38.0](https://github.com/launchdarkly/observability-sdk/compare/launchdarkly-observability-android-0.37.0...launchdarkly-observability-android-0.38.0) (2026-04-13)
411

512

sdk/@launchdarkly/observability-android/gradle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,5 @@ android.useAndroidX=true
55
org.jetbrains.dokka.experimental.gradle.pluginMode=V2EnabledWithHelpers
66

77
#x-release-please-start-version
8-
version=0.38.0
8+
version=0.39.0
99
#x-release-please-end

sdk/@launchdarkly/react-native-ld-session-replay/CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
# Changelog
22

3+
## [0.4.0](https://github.com/launchdarkly/observability-sdk/compare/session-replay-react-native-0.3.0...session-replay-react-native-0.4.0) (2026-04-17)
4+
5+
6+
### Features
7+
8+
* [SDK-2121] implement session replay for react native android ([#456](https://github.com/launchdarkly/observability-sdk/issues/456)) ([a5af1d8](https://github.com/launchdarkly/observability-sdk/commit/a5af1d8368fc06ffbef9b486f4b40cbfd7390ef3))
9+
* [SDK-2190] add dialogs to the RN session replay example app ([#471](https://github.com/launchdarkly/observability-sdk/issues/471)) ([c677962](https://github.com/launchdarkly/observability-sdk/commit/c6779627f17bdb161b4fb79092dd6743ad54f9bf))
10+
311
## [0.3.0](https://github.com/launchdarkly/observability-sdk/compare/session-replay-react-native-0.2.2...session-replay-react-native-0.3.0) (2026-03-26)
412

513

sdk/@launchdarkly/react-native-ld-session-replay/android/build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ def kotlin_version = getExtOrDefault("kotlinVersion")
8383
dependencies {
8484
implementation "com.facebook.react:react-android"
8585
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
86-
implementation "com.launchdarkly:launchdarkly-observability-android:0.34.1"
86+
implementation "com.launchdarkly:launchdarkly-observability-android:0.39.0"
8787
implementation "com.launchdarkly:launchdarkly-android-client-sdk:5.11.0"
8888
// compileOnly: OTel Attributes appears in ObservabilityOptions parameter types; provided at
8989
// runtime transitively through launchdarkly-observability-android.

sdk/@launchdarkly/react-native-ld-session-replay/android/src/main/java/com/sessionreplayreactnative/SessionReplayClientAdapter.kt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.sessionreplayreactnative
22

3+
import android.app.Activity
34
import android.app.Application
45
import android.os.Handler
56
import android.os.Looper
@@ -39,7 +40,7 @@ internal class SessionReplayClientAdapter private constructor() {
3940
}
4041
}
4142

42-
fun start(application: Application, completion: (Boolean, String?) -> Unit) {
43+
fun start(application: Application, activity: Activity?, completion: (Boolean, String?) -> Unit) {
4344
val localMobileKey: String?
4445
val localServiceName: String
4546
val localReplayOptions: ReplayOptions?
@@ -70,6 +71,9 @@ internal class SessionReplayClientAdapter private constructor() {
7071
return@post
7172
}
7273
initialized = true
74+
// React Native is often initialized after the main activity has already been
75+
// created, so we miss its lifecycle events. Manually register it, just in case.
76+
activity?.let { LDReplay.registerActivity(it) }
7377
} else {
7478
logger.debug("start: already initialized, re-applying isEnabled={0}", localReplayOptions.enabled)
7579
}

sdk/@launchdarkly/react-native-ld-session-replay/android/src/main/java/com/sessionreplayreactnative/SessionReplayReactNativeModule.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ class SessionReplayReactNativeModule(reactContext: ReactApplicationContext) :
3333
return
3434
}
3535
try {
36-
SessionReplayClientAdapter.shared.start(application) { success, errorMessage ->
36+
SessionReplayClientAdapter.shared.start(application, reactApplicationContext.getCurrentActivity()) { success, errorMessage ->
3737
if (success) {
3838
promise.resolve(null)
3939
} else {

sdk/@launchdarkly/react-native-ld-session-replay/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@launchdarkly/session-replay-react-native",
3-
"version": "0.3.0",
3+
"version": "0.4.0",
44
"description": "session replay for react native",
55
"main": "./lib/module/index.js",
66
"types": "./lib/typescript/src/index.d.ts",

0 commit comments

Comments
 (0)