Skip to content

Fix RUM-13135: Compose Instrumentation modifying expected layout#3249

Draft
mariusc83 wants to merge 4 commits intodevelopfrom
mariusc83/RUM-13135/compose-instrumentation-layout
Draft

Fix RUM-13135: Compose Instrumentation modifying expected layout#3249
mariusc83 wants to merge 4 commits intodevelopfrom
mariusc83/RUM-13135/compose-instrumentation-layout

Conversation

@mariusc83
Copy link
Member

@mariusc83 mariusc83 commented Mar 11, 2026

Summary

Fixes layout constraint propagation issue caused by Datadog Compose auto-instrumentation. When the compiler plugin prepends Modifier.semantics {} to composable modifier chains, it can interfere with SubcomposeLayout-based components (e.g., Coil's SubcomposeAsyncImage) inside LazyRow/LazyColumn, causing hasBoundedHeight to become false and minHeight to become 0.

RUM-13135

Root Cause

The Datadog Kotlin Compiler Plugin (ComposeTagTransformer) auto-instruments composable functions by inserting instrumentedDatadog(name).then(originalModifier) at every composable call site. The instrumentedDatadog() function previously used Modifier.semantics {} (from CoreSemanticsModifierNode), which in certain Compose framework versions may participate in the layout measurement chain, modifying constraint propagation.

Changes

  • DatadogModifier.kt: Replaced Modifier.semantics {} with custom DatadogSemanticsElement/DatadogSemanticsNode using the ModifierNodeElement API
    • DatadogSemanticsNode explicitly implements only SemanticsModifierNode (NOT LayoutModifierNode)
    • Guarantees the node never interferes with layout constraint measurement
    • DatadogSemanticsPropertyKey and public Modifier.datadog() API remain unchanged
  • DatadogSemanticsElementTest.kt: 7 unit tests for the new element/node

Companion Change (separate repo)

dd-sdk-android-gradle-plugin: ComposeTagTransformer.buildIrExpression() should change modifier order from datadogTag.then(original) to original.then(datadogTag), placing semantics INNER instead of OUTER so layout modifiers process constraints first.

Test Plan

  • New unit tests for DatadogSemanticsElement and DatadogSemanticsNode
  • All existing compose module tests pass
  • Public API surface unchanged
  • Integration test with LazyRow + SubcomposeAsyncImage (requires Android emulator)
  • Compiler plugin companion PR

Generated by rum:fix-jira-issues

…ment

Root cause: The Datadog Kotlin Compiler Plugin prepends Modifier.semantics {}
to every composable call's modifier chain. In certain Compose versions, the
CoreSemanticsModifierNode implementation may participate in the layout
measurement chain, causing constraint propagation issues in SubcomposeLayout-
based components (e.g., Coil SubcomposeAsyncImage) inside LazyRow/LazyColumn.

Changes:
- Replace Modifier.semantics {} with custom DatadogSemanticsElement/Node
- DatadogSemanticsNode explicitly implements only SemanticsModifierNode
- Node is guaranteed to never interfere with layout constraints
- DatadogSemanticsPropertyKey and public API remain unchanged

Tests: 7 unit
Apply ktlint standard:class-signature and standard:function-signature
rules to DatadogSemanticsElement, DatadogSemanticsNode, and test methods.
…shCode

Convert DatadogSemanticsElement from data class to regular class to avoid
detekt DataClassContainsFunctions violation. Manually implement equals()
and hashCode() to maintain the same behavior for Compose modifier reuse.
Revert ktlint auto-format to use multi-line class and function signatures
that match the existing project style conventions (parameters on separate
lines when there are 2+ parameters).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant