Skip to content

Commit e59b24c

Browse files
Merge branch 'develop' into aleksandr-gringauz/update-docker-image-to-jammy
2 parents f65cc6d + a213cc7 commit e59b24c

File tree

7 files changed

+60
-30
lines changed

7 files changed

+60
-30
lines changed

CONTRIBUTING.md

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,23 +24,28 @@ In addition, to be able to run the static analysis tools locally, you should run
2424
This project hosts the following modules:
2525

2626
- `dd-sdk-android-core`: the main library implementing the core functionality of SDK (storage and upload of data, core APIs);
27+
- `dd-sdk-android-internal`: a library providing internal APIs, classes and utilities shared by the SDK modules;
2728
- `features/***`: a set of libraries implementing Datadog products:
2829
- `features/dd-sdk-android-logs`: a library to send logs to Datadog;
2930
- `features/dd-sdk-android-rum`: a library to track user navigation and interaction;
3031
- `features/dd-sdk-android-ndk`: a lightweight library to track crashes from NDK libraries;
3132
- `features/dd-sdk-android-session-replay`: a library to capture the window content;
33+
- `features/dd-sdk-android-session-replay-compose`: an extension for Session Replay to integrate with the Jetpack Compose;
3234
- `features/dd-sdk-android-session-replay-material`: an extension for Session Replay to integrate with the Material Design library;
33-
- `features/dd-sdk-android-session-trace`: a library to measure performance of operations locally;
34-
- `features/dd-sdk-android-session-webview`: a library to forward logs and RUM events captured in a webview to be linked with the mobile session;
35+
- `features/dd-sdk-android-trace`: a library to measure performance of operations locally;
36+
- `features/dd-sdk-android-trace-otel`: an extension of Trace library to integrate with OpenTelemetry;
37+
- `features/dd-sdk-android-webview`: a library to forward logs and RUM events captured in a webview to be linked with the mobile session;
3538
- `integrations/***`: a set of libraries integrating Datadog products in third party libraries:
3639
- `integrations/dd-sdk-android-coil`: a lightweight library providing a bridge integration between Datadog SDK and [Coil](https://coil-kt.github.io/coil/);
3740
- `integrations/dd-sdk-android-compose`: a lightweight library providing a bridge integration between Datadog SDK and [Jetpack Compose](https://developer.android.com/jetpack/compose);
3841
- `integrations/dd-sdk-android-fresco`: a lightweight library providing a bridge integration between Datadog SDK and [Fresco](https://frescolib.org/);
3942
- `integrations/dd-sdk-android-okhttp`: a lightweight library providing an instrumentation for [OkHttp](https://square.github.io/okhttp/);
43+
- `integrations/dd-sdk-android-okhttp-otel`: a lightweight library a support of OpenTelemetry for the [OkHttp](https://square.github.io/okhttp/) instrumentation;
4044
- `integrations/dd-sdk-android-rx`: a lightweight library providing a bridge integration between Datadog SDK and [RxJava](https://github.com/ReactiveX/RxJava);
4145
- `integrations/dd-sdk-android-sqldelight`: a lightweight library providing a bridge integration between Datadog SDK and [SQLDelight](https://cashapp.github.io/sqldelight/);
4246
- `integrations/dd-sdk-android-tv`: a lightweight library providing extensions for [Android TV](https://www.android.com/tv/)
43-
- `integrations/dd-sdk-android-ktx`: a set of Kotlin extensions to make the Datadog SDK more Kotlin friendly;
47+
- `integrations/dd-sdk-android-trace-coroutines`: a set of extensions for Kotlin Coroutines to ease the work with the Trace library;
48+
- `integrations/dd-sdk-android-rum-coroutines`: a set of extensions for Kotlin Coroutines to ease the work with the RUM library;
4449
- `integrations/dd-sdk-android-glide`: a lightweight library providing a bridge integration between Datadog SDK and [Glide](https://bumptech.github.io/glide/);
4550
- `integrations/dd-sdk-android-timber`: a lightweight library providing a bridge integration between Datadog SDK and [Timber](https://github.com/JakeWharton/timber);
4651
- `instrumented/***`: a set of modules used to run instrumented tests:
@@ -52,8 +57,11 @@ This project hosts the following modules:
5257
- `tools/unit`: a utility library with code to help writing unit tests;
5358
- `sample/***`: a few sample applications showcasing how to use the library features in production code;
5459
- `sample/kotlin`: a sample mobile application;
55-
- `sample/vendor-lib`: a sample android library, to showcase vendors using Datadog in a host app also using Datadog;
56-
- `sample/wear`: a sample watch application;
60+
- `sample/vendor-lib`: a sample Android library, to showcase vendors using Datadog in a host app also using Datadog;
61+
- `sample/wear`: a sample Wear OS application;
62+
- `sample/automotive`: a sample Automotive OS application;
63+
- `sample/tv`: a sample Android TV OS application;
64+
- `sample/benchmark`: a sample application to collect SDK performance metrics;
5765

5866
### Building the SDK
5967

features/dd-sdk-android-session-replay/src/main/kotlin/com/datadog/android/sessionreplay/internal/async/RecordedDataQueueHandler.kt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,6 @@ internal class RecordedDataQueueHandler(
9999
* for example if a snapshot failed to traverse the tree).
100100
* If neither of the previous conditions occurs, the loop breaks.
101101
*/
102-
@MainThread
103102
override fun tryToConsumeItems() {
104103
// no need to create a thread if the queue is empty
105104
if (recordedDataQueue.isEmpty()) {

features/dd-sdk-android-session-replay/src/main/kotlin/com/datadog/android/sessionreplay/internal/async/RecordedDataQueueRefs.kt

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,11 @@
66

77
package com.datadog.android.sessionreplay.internal.async
88

9-
import android.os.Handler
10-
import android.os.Looper
11-
129
/**
1310
* References to the work queue context.
1411
*/
1512
internal data class RecordedDataQueueRefs(
16-
private val recordedDataQueueHandler: RecordedDataQueueHandler,
17-
private val mainThreadHandler: Handler = Handler(Looper.getMainLooper())
13+
private val recordedDataQueueHandler: RecordedDataQueueHandler
1814
) {
1915
// this can only be populated after the snapshot has been created
2016
internal var recordedDataQueueItem: SnapshotRecordedDataQueueItem? = null
@@ -28,9 +24,6 @@ internal data class RecordedDataQueueRefs(
2824
}
2925

3026
internal fun tryToConsumeItem() {
31-
mainThreadHandler.post {
32-
@Suppress("ThreadSafety") // we are in the main thread context
33-
recordedDataQueueHandler.tryToConsumeItems()
34-
}
27+
recordedDataQueueHandler.tryToConsumeItems()
3528
}
3629
}

features/dd-sdk-android-session-replay/src/main/kotlin/com/datadog/android/sessionreplay/internal/processor/NodeFlattener.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ internal class NodeFlattener(private val wireframeUtils: WireframeUtils = Wirefr
1919
stack.push(root)
2020
while (stack.isNotEmpty()) {
2121
val node = stack.pop()
22-
node.wireframes
22+
node.wireframes.toList()
2323
.map { wireframe ->
2424
val clip = wireframeUtils.resolveWireframeClip(wireframe, node.parents)
2525
wireframe.copy(clip = clip)

features/dd-sdk-android-session-replay/src/test/kotlin/com/datadog/android/sessionreplay/internal/async/RecordedDataQueueRefsTest.kt

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66

77
package com.datadog.android.sessionreplay.internal.async
88

9-
import android.os.Handler
109
import com.datadog.android.sessionreplay.forge.ForgeConfigurator
1110
import fr.xgouchet.elmyr.junit5.ForgeConfiguration
1211
import fr.xgouchet.elmyr.junit5.ForgeExtension
@@ -15,10 +14,8 @@ import org.junit.jupiter.api.Test
1514
import org.junit.jupiter.api.extension.ExtendWith
1615
import org.junit.jupiter.api.extension.Extensions
1716
import org.mockito.Mock
18-
import org.mockito.Mockito.`when`
1917
import org.mockito.junit.jupiter.MockitoExtension
2018
import org.mockito.junit.jupiter.MockitoSettings
21-
import org.mockito.kotlin.any
2219
import org.mockito.kotlin.verify
2320
import org.mockito.quality.Strictness
2421

@@ -37,18 +34,9 @@ internal class RecordedDataQueueRefsTest {
3734
@Mock
3835
lateinit var mockRecordedDataQueueItem: SnapshotRecordedDataQueueItem
3936

40-
@Mock
41-
lateinit var mockHandler: Handler
42-
4337
@BeforeEach
4438
fun setup() {
45-
// make mockHandler execute all runnables immediately
46-
`when`(mockHandler.post(any())).thenAnswer {
47-
(it.arguments[0] as Runnable).run()
48-
true
49-
}
50-
51-
testedDataQueueRefs = RecordedDataQueueRefs(mockDataQueueHandler, mockHandler)
39+
testedDataQueueRefs = RecordedDataQueueRefs(mockDataQueueHandler)
5240
testedDataQueueRefs.recordedDataQueueItem = mockRecordedDataQueueItem
5341
}
5442

features/dd-sdk-android-session-replay/src/test/kotlin/com/datadog/android/sessionreplay/internal/processor/NodeFlattenerTest.kt

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import fr.xgouchet.elmyr.junit5.ForgeExtension
1515
import org.assertj.core.api.Assertions.assertThat
1616
import org.junit.jupiter.api.BeforeEach
1717
import org.junit.jupiter.api.Test
18+
import org.junit.jupiter.api.assertDoesNotThrow
1819
import org.junit.jupiter.api.extension.ExtendWith
1920
import org.junit.jupiter.api.extension.Extensions
2021
import org.mockito.Mock
@@ -25,7 +26,6 @@ import org.mockito.kotlin.eq
2526
import org.mockito.kotlin.whenever
2627
import org.mockito.quality.Strictness
2728
import java.util.LinkedList
28-
import kotlin.collections.ArrayList
2929
import kotlin.math.pow
3030

3131
@Extensions(
@@ -135,10 +135,51 @@ internal class NodeFlattenerTest {
135135
assertThat(wireframes).isEqualTo(expectedList)
136136
}
137137

138+
@Test
139+
fun `M not have ConcurrentModificationException W modifying nodes concurrently`(forge: Forge) {
140+
// Given
141+
val maxWidth = forge.aLong(2, 1000)
142+
val maxHeight = forge.aLong(2, 1000)
143+
val wireframeSize = forge.anInt(min = 10, max = 100)
144+
val expectedList: MutableList<MobileSegment.Wireframe> =
145+
Array<MobileSegment.Wireframe>(wireframeSize) {
146+
// just to avoid collisions we will add the wireframes manually
147+
val width = forge.aLong(min = 1, max = maxWidth)
148+
val height = forge.aLong(min = 1, max = maxHeight)
149+
val x = it * maxWidth
150+
val y = it * maxHeight
151+
forge.getForgery<MobileSegment.Wireframe.ShapeWireframe>()
152+
.copy(width = width, height = height, x = x, y = y)
153+
}.toMutableList()
154+
val fakeSnapshot = generateFlattenNodeFromList(expectedList)
155+
156+
// When
157+
val thread = Thread {
158+
repeat(forge.anInt(1, wireframeSize - 1)) {
159+
expectedList.removeAt(0)
160+
}
161+
}
162+
163+
// Then
164+
assertDoesNotThrow {
165+
thread.start()
166+
testedNodeFlattener.flattenNode(fakeSnapshot)
167+
thread.join()
168+
}
169+
}
170+
138171
// endregion
139172

140173
// region Internals
141174

175+
private fun generateFlattenNodeFromList(list: List<MobileSegment.Wireframe>): Node {
176+
return Node(
177+
wireframes = list,
178+
children = emptyList(),
179+
parents = emptyList()
180+
)
181+
}
182+
142183
private fun generateTreeFromList(list: List<MobileSegment.Wireframe>): Node {
143184
val mutableList = list.toMutableList()
144185
val root = mutableList.removeAt(0).toNode()

local_ci.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ if [[ $CLEANUP == 1 ]]; then
102102
rm -rf features/dd-sdk-android-ndk/build/
103103
rm -rf features/dd-sdk-android-rum/build/
104104
rm -rf features/dd-sdk-android-session-replay/build/
105+
rm -rf features/dd-sdk-android-session-replay-compose/build/
105106
rm -rf features/dd-sdk-android-session-replay-material/build/
106107
rm -rf features/dd-sdk-android-trace/build/
107108
rm -rf features/dd-sdk-android-trace-otel/build/

0 commit comments

Comments
 (0)