Allow bridging Sentry spans to the SDK ones.
Add distributed tracing for `Room.timelineWithConfiguration`, so we can inspect the associated Rust trace.
This commit is contained in:
parent
6c404fda36
commit
bd427735ff
15 changed files with 195 additions and 10 deletions
|
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* Copyright (c) 2025 Element Creations Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.matrix.impl.analytics
|
||||
|
||||
import dev.zacsweers.metro.AppScope
|
||||
import dev.zacsweers.metro.ContributesBinding
|
||||
import io.element.android.services.analytics.api.AnalyticsSdkSpan
|
||||
import io.element.android.services.analytics.api.AnalyticsSdkSpanFactory
|
||||
|
||||
@ContributesBinding(AppScope::class)
|
||||
class DefaultAnalyticsSdkFactory : AnalyticsSdkSpanFactory {
|
||||
override fun create(name: String, parentTraceId: String?): AnalyticsSdkSpan {
|
||||
return RustAnalyticsSdkSpan(name = name, parentTraceId = parentTraceId)
|
||||
}
|
||||
|
||||
override fun bridge(parentTraceId: String?): AnalyticsSdkSpan {
|
||||
// A bridge span has no name
|
||||
return RustAnalyticsSdkSpan(name = null, parentTraceId = parentTraceId)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* Copyright (c) 2025 Element Creations Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.matrix.impl.analytics
|
||||
|
||||
import io.element.android.libraries.core.extensions.runCatchingExceptions
|
||||
import io.element.android.services.analytics.api.AnalyticsSdkSpan
|
||||
import kotlinx.coroutines.DelicateCoroutinesApi
|
||||
import org.matrix.rustcomponents.sdk.LogLevel
|
||||
import org.matrix.rustcomponents.sdk.Span
|
||||
import timber.log.Timber
|
||||
|
||||
class RustAnalyticsSdkSpan(
|
||||
name: String? = null,
|
||||
private val parentTraceId: String?,
|
||||
) : AnalyticsSdkSpan {
|
||||
private val inner = if (name != null) {
|
||||
Span(
|
||||
target = "elementx",
|
||||
name = name,
|
||||
file = "-",
|
||||
line = null,
|
||||
level = LogLevel.WARN,
|
||||
bridgeTraceId = parentTraceId,
|
||||
)
|
||||
} else {
|
||||
Span.newBridgeSpan(
|
||||
target = "elementx",
|
||||
parentTraceId = parentTraceId,
|
||||
)
|
||||
}
|
||||
|
||||
override fun enter() {
|
||||
if (Span.current().isNone()) {
|
||||
inner.enter()
|
||||
} else {
|
||||
Timber.w("Not entering span sentry.trace='$parentTraceId' because another span is already active")
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(DelicateCoroutinesApi::class)
|
||||
override fun exit() {
|
||||
inner.exit()
|
||||
runCatchingExceptions { inner.destroy() }
|
||||
Timber.d("Exited span sentry.trace='$parentTraceId'")
|
||||
}
|
||||
}
|
||||
|
|
@ -25,6 +25,7 @@ import io.element.android.libraries.matrix.impl.room.preview.RoomPreviewInfoMapp
|
|||
import io.element.android.libraries.matrix.impl.roomlist.roomOrNull
|
||||
import io.element.android.services.analytics.api.AnalyticsLongRunningTransaction
|
||||
import io.element.android.services.analytics.api.AnalyticsService
|
||||
import io.element.android.services.analytics.api.inBridgeSdkSpan
|
||||
import io.element.android.services.analytics.api.recordTransaction
|
||||
import io.element.android.services.analyticsproviders.api.recordChildTransaction
|
||||
import io.element.android.services.toolbox.api.systemclock.SystemClock
|
||||
|
|
@ -127,17 +128,19 @@ class RustRoomFactory(
|
|||
val timeline = transaction.recordChildTransaction(
|
||||
operation = "sdkRoom.timelineWithConfiguration",
|
||||
description = "Get timeline from the SDK",
|
||||
) {
|
||||
sdkRoom.timelineWithConfiguration(
|
||||
TimelineConfiguration(
|
||||
focus = TimelineFocus.Live(hideThreadedEvents = hideThreadedEvents),
|
||||
filter = eventFilters?.let(TimelineFilter::EventTypeFilter) ?: TimelineFilter.All,
|
||||
internalIdPrefix = "live",
|
||||
dateDividerMode = DateDividerMode.DAILY,
|
||||
trackReadReceipts = TimelineReadReceiptTracking.ALL_EVENTS,
|
||||
reportUtds = true,
|
||||
) { timelineTransaction ->
|
||||
analyticsService.inBridgeSdkSpan(parentTraceId = timelineTransaction.traceId()) {
|
||||
sdkRoom.timelineWithConfiguration(
|
||||
TimelineConfiguration(
|
||||
focus = TimelineFocus.Live(hideThreadedEvents = hideThreadedEvents),
|
||||
filter = eventFilters?.let(TimelineFilter::EventTypeFilter) ?: TimelineFilter.All,
|
||||
internalIdPrefix = "live",
|
||||
dateDividerMode = DateDividerMode.DAILY,
|
||||
trackReadReceipts = TimelineReadReceiptTracking.ALL_EVENTS,
|
||||
reportUtds = true,
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
GetRoomResult.Joined(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue