Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[QA] Make replay lazy and faster #3799

Merged
merged 4 commits into from
Oct 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
- Fix potential ANRs due to NDK System.loadLibrary calls ([#3670](https://github.com/getsentry/sentry-java/pull/3670))
- Fix slow `Log` calls on app startup ([#3793](https://github.com/getsentry/sentry-java/pull/3793))
- Fix slow Integration name parsing ([#3794](https://github.com/getsentry/sentry-java/pull/3794))
- Session Replay: Reduce startup and capture overhead ([#3799](https://github.com/getsentry/sentry-java/pull/3799))

## 7.15.0

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,16 @@ import kotlin.LazyThreadSafetyMode.NONE
public open class DefaultReplayBreadcrumbConverter : ReplayBreadcrumbConverter {
internal companion object {
private val snakecasePattern by lazy(NONE) { "_[a-z]".toRegex() }
private val supportedNetworkData = setOf(
"status_code",
"method",
"response_content_length",
"request_content_length",
"http.response_content_length",
"http.request_content_length"
)
private val supportedNetworkData by lazy(NONE) {
setOf(
"status_code",
"method",
"response_content_length",
"request_content_length",
"http.response_content_length",
"http.request_content_length"
)
}
}

private var lastConnectivityState: String? = null
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import java.util.concurrent.Executors
import java.util.concurrent.ThreadFactory
import java.util.concurrent.atomic.AtomicBoolean
import java.util.concurrent.atomic.AtomicReference
import kotlin.LazyThreadSafetyMode.NONE
import kotlin.math.roundToInt

@TargetApi(26)
Expand All @@ -51,15 +52,19 @@ internal class ScreenshotRecorder(
}
private var rootView: WeakReference<View>? = null
private val pendingViewHierarchy = AtomicReference<ViewHierarchyNode>()
private val maskingPaint = Paint()
private val singlePixelBitmap: Bitmap = Bitmap.createBitmap(
1,
1,
Bitmap.Config.ARGB_8888
)
private val singlePixelBitmapCanvas: Canvas = Canvas(singlePixelBitmap)
private val prescaledMatrix = Matrix().apply {
preScale(config.scaleFactorX, config.scaleFactorY)
private val maskingPaint by lazy(NONE) { Paint() }
private val singlePixelBitmap: Bitmap by lazy(NONE) {
Bitmap.createBitmap(
1,
1,
Bitmap.Config.ARGB_8888
)
}
private val singlePixelBitmapCanvas: Canvas by lazy(NONE) { Canvas(singlePixelBitmap) }
private val prescaledMatrix by lazy(NONE) {
Matrix().apply {
preScale(config.scaleFactorX, config.scaleFactorY)
}
}
private val contentChanged = AtomicBoolean(false)
private val isCapturing = AtomicBoolean(true)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -209,10 +209,6 @@ internal abstract class BaseCaptureStrategy(
}
}

init {
runInBackground { onChange(propertyName, initialValue, initialValue) }
}

override fun getValue(thisRef: Any?, property: KProperty<*>): T? = value.get()

override fun setValue(thisRef: Any?, property: KProperty<*>, value: T?) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import androidx.compose.ui.graphics.isUnspecified
import androidx.compose.ui.graphics.toArgb
import androidx.compose.ui.layout.LayoutCoordinates
import androidx.compose.ui.layout.findRootCoordinates
import androidx.compose.ui.layout.positionInWindow
import androidx.compose.ui.node.LayoutNode
import androidx.compose.ui.node.Owner
import androidx.compose.ui.semantics.SemanticsActions
Expand Down Expand Up @@ -87,12 +86,13 @@ internal object ComposeViewHierarchyNode {
(semantics == null || !semantics.contains(SemanticsProperties.InvisibleToUser)) &&
visibleRect.height() > 0 && visibleRect.width() > 0
val isEditable = semantics?.contains(SemanticsActions.SetText) == true
val positionInWindow = node.coordinates.positionInWindow()
return when {
semantics?.contains(SemanticsProperties.Text) == true || isEditable -> {
val shouldMask = isVisible && node.shouldMask(isImage = false, options)

parent?.setImportantForCaptureToAncestors(true)
// TODO: if we get reports that it's slow, we can drop this, and just mask
// TODO: the whole view instead of per-line
val textLayoutResults = mutableListOf<TextLayoutResult>()
semantics?.getOrNull(SemanticsActions.GetTextLayoutResult)
?.action
Expand All @@ -108,8 +108,8 @@ internal object ComposeViewHierarchyNode {
TextViewHierarchyNode(
layout = if (textLayoutResults.isNotEmpty() && !isEditable) ComposeTextLayout(textLayoutResults.first(), hasFillModifier) else null,
dominantColor = textColor?.toArgb()?.toOpaque(),
x = positionInWindow.x,
y = positionInWindow.y,
x = visibleRect.left.toFloat(),
y = visibleRect.top.toFloat(),
width = node.width,
height = node.height,
elevation = (parent?.elevation ?: 0f),
Expand All @@ -128,8 +128,8 @@ internal object ComposeViewHierarchyNode {

parent?.setImportantForCaptureToAncestors(true)
ImageViewHierarchyNode(
x = positionInWindow.x,
y = positionInWindow.y,
x = visibleRect.left.toFloat(),
y = visibleRect.top.toFloat(),
width = node.width,
height = node.height,
elevation = (parent?.elevation ?: 0f),
Expand All @@ -147,8 +147,8 @@ internal object ComposeViewHierarchyNode {
// TODO: traverse the ViewHierarchyNode here again. For now we can recommend
// TODO: using custom modifiers to obscure the entire node if it's sensitive
GenericViewHierarchyNode(
x = positionInWindow.x,
y = positionInWindow.y,
x = visibleRect.left.toFloat(),
y = visibleRect.top.toFloat(),
width = node.width,
height = node.height,
elevation = (parent?.elevation ?: 0f),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -239,8 +239,8 @@ sealed class ViewHierarchyNode(
private fun Class<*>.isAssignableFrom(set: Set<String>): Boolean {
var cls: Class<*>? = this
while (cls != null) {
val canonicalName = cls.canonicalName
if (canonicalName != null && set.contains(canonicalName)) {
val canonicalName = cls.name
if (set.contains(canonicalName)) {
return true
}
cls = cls.superclass
Expand Down
Loading