Compose में स्टैक ट्रेस

Jetpack Compose, आपके कोड को अलग-अलग फ़ेज़ में एक्ज़ीक्यूट करता है. इस वजह से, @Composable फ़ंक्शन के कुछ हिस्सों को एक-दूसरे से अलग एक्ज़ीक्यूट किया जाता है. इन फ़ेज़ में क्रैश होने पर, ऐसे स्टैक ट्रेस मिल सकते हैं जिन्हें समझना मुश्किल होता है. इससे उस फ़ंक्शन या कोड की लाइन का पता लगाना मुश्किल हो जाता है जिसकी वजह से क्रैश हुआ.

स्टैक ट्रेस में सोर्स की जानकारी जोड़ना

स्टैक ट्रेस को आसानी से पढ़ने के लिए, ऑप्ट-इन एपीआई क्रैश की जगह की ज़्यादा जानकारी देता है. इसमें कंपोज़ेबल के नाम और जगह की जानकारी शामिल होती है. इससे आपको ये काम करने में मदद मिलती है:

  • क्रैश की वजहों का पता लगाना और उन्हें ठीक करना
  • दोहराए जा सकने वाले सैंपल के लिए क्रैश अलग करना
  • उन क्रैश की जांच करें जिनमें पहले सिर्फ़ इंटरनल स्टैक फ़्रेम दिखते थे

Compose रनटाइम, कंपोज़िशन में क्रैश की जगह का पता लगा सकता है. साथ ही, आपकी @Composable हैरारकी के आधार पर स्टैक ट्रेस को फिर से बना सकता है. स्टैक ट्रेस को इन क्रैश के लिए जोड़ा जाता है:

  • कंपोज़िशन
  • DisposableEffect और LaunchedEffect (onDispose या रद्द करने के अलावा)
  • rememberCoroutineScope में लॉन्च की गई कोरूटीन
  • मेज़रमेंट, लेआउट, और ड्रॉ पास

इस सुविधा को चालू करने के लिए, ऐप्लिकेशन के एंट्री पॉइंट में ये लाइनें जोड़ें:

// Enable stack traces at application level: onCreate
class SampleStackTracesEnabledApp : Application() {

    override fun onCreate() {
        super.onCreate()
        // Enable Compose stack traces for minified builds only.
        Composer.setDiagnosticStackTraceMode(ComposeStackTraceMode.Auto)

        // Alternatively:
        // Enable verbose Compose stack traces for local debugging
        Composer.setDiagnosticStackTraceMode(ComposeStackTraceMode.SourceInformation)
    }
}

हमारा सुझाव है कि कंपोज़िशन बनाने से पहले, इस कॉन्फ़िगरेशन को पूरा करें. इससे यह पुष्टि की जा सकेगी कि स्टैक ट्रेस की जानकारी सही तरीके से इकट्ठा की गई है.

ComposeStackTraceMode के लिए, ये चार विकल्प उपलब्ध हैं:

  • Auto: यह विकल्प इस्तेमाल करने का सुझाव दिया जाता है, क्योंकि अगर ऐप्लिकेशन को छोटा किया गया है, तो यह GroupKeys का इस्तेमाल करता है. अगर ऐसा नहीं है, तो यह None का इस्तेमाल करता है.
  • GroupKeys: स्टैक ट्रेस, छोटे किए गए ऐप्लिकेशन के लिए बनाए जाते हैं. काट-छांट करने के बाद भी, ग्रुप की मुख्य जानकारी सेव रहती है. इसका इस्तेमाल, Compose कंपाइलर और R8 से मिली proguard मैपिंग फ़ाइल के साथ किया जाता है. इससे @Composable फ़ंक्शन की जगह की जानकारी का अनुमान लगाया जा सकता है. ये स्टैक ट्रेस कम सटीक होते हैं. इन्हें इस तरह से ऑप्टिमाइज़ किया जाता है कि रनटाइम के दौरान अतिरिक्त काम न करना पड़े. Compose कंपाइलर, Kotlin 2.3.0 से R8 मैपिंग के अतिरिक्त उत्सर्जन का समर्थन करता है.
  • SourceInformation: यह विकल्प, बिना छोटा किए गए बिल्ड के लिए काम का है. यह सोर्स की जानकारी इकट्ठा करता है और उसे स्टैक ट्रेस में जोड़ता है. इसके नतीजे ज़्यादा सटीक होते हैं. हालांकि, इससे परफ़ॉर्मेंस पर काफ़ी असर पड़ता है. यह लेआउट इंस्पेक्टर को अटैच करने जैसा ही है. इन्हें ऐप्लिकेशन के डीबग वर्शन में इस्तेमाल करने के लिए बनाया जाता है. इससे क्रैश की सटीक जानकारी मिलती है. साथ ही, क्रैश की जगह के बारे में ज़्यादा जानकारी मिलती है. सोर्स कोड की जानकारी को छोटे किए गए ऐप्लिकेशन से हटा दिया जाता है, ताकि बाइनरी के साइज़ और परफ़ॉर्मेंस को ऑप्टिमाइज़ किया जा सके.
  • None: स्टैक ट्रेस की कोई अतिरिक्त जानकारी नहीं जोड़ी गई है.

SourceInformation विकल्प का इस्तेमाल करने पर, स्टैक ट्रेस को दबाए गए अपवाद की सूची में SourceInformation के तौर पर दिखाया जाता है:DiagnosticComposeException

java.lang.IllegalStateException: Test layout error
    at <original trace>
Suppressed: androidx.compose.runtime.DiagnosticComposeException:
Composition stack when thrown:
    at ReusableComposeNode(Composables.kt:<unknown line>)
    at Layout(Layout.kt:79)
    at <lambda>(TempErrorsTest.kt:164)
    at <lambda>(BoxWithConstraints.kt:66)
    at ReusableContentHost(Composables.kt:164)
    at <lambda>(SubcomposeLayout.kt:514)
    at SubcomposeLayout(SubcomposeLayout.kt:114)
    at SubcomposeLayout(SubcomposeLayout.kt:80)
    at BoxWithConstraints(BoxWithConstraints.kt:64)
    at SubcomposeLayoutErrorComposable(TempErrorsTest.kt:164)
    at <lambda>(TempErrorsTest.kt:86)
    at Content(ComposeView.android.kt:430)
    at <lambda>(ComposeView.android.kt:249)
    at CompositionLocalProvider(CompositionLocal.kt:364)
    at ProvideCommonCompositionLocals(CompositionLocals.kt:193)
    at <lambda>(AndroidCompositionLocals.android.kt:113)
    at CompositionLocalProvider(CompositionLocal.kt:364)
    at ProvideAndroidCompositionLocals(AndroidCompositionLocals.android.kt:102)
    at <lambda>(Wrapper.android.kt:141)
    at CompositionLocalProvider(CompositionLocal.kt:384)
    at <lambda>(Wrapper.android.kt:140)

सीमाएं

स्टैक ट्रेस फ़्रेम से जुड़ी कुछ समस्याएं हैं:

सोर्स की जानकारी वाले स्टैक ट्रेस

कंपोज़िशन में क्रैश होने की वजह से, पहले स्टैक फ़्रेम में लाइन नंबर (<unknown line>) मौजूद नहीं हैं. क्रैश होने के बाद, सोर्स की जानकारी की जांच की जाती है. इसलिए, स्लॉट टेबल का डेटा अधूरा हो सकता है और लाइन नंबर कम हो सकता है. ReusableComposeNode और remember से सोर्स की जानकारी नहीं मिलती. इसलिए, आपको उन फ़ंक्शन के स्टैक फ़्रेम में <unknown line> दिखेगा.

ग्रुप किए गए कुंजियों के स्टैक ट्रेस

GroupKeys पर आधारित स्टैक ट्रेस, डिज़ाइन के हिसाब से सिर्फ़ @Composable फ़ंक्शन की पहली लाइन की ओर इशारा कर सकते हैं. इनमें ऐसे फ़ंक्शन के लिए भी कोई डेटा नहीं होता जो ग्रुप नहीं बनाते. जैसे, इनलाइन या नॉन-यूनिट फ़ंक्शन

स्टैक ट्रेस इकट्ठा करने के दौरान क्रैश होना

अगर स्टैक ट्रेस कलेक्शन किसी वजह से क्रैश हो जाता है, तो उस अपवाद को DiagnosticComposeException के बजाय, दबाए गए अपवाद के तौर पर जोड़ा जाता है.

दबाए गए क्रैश या स्टैक ट्रेस में मौजूद किसी भी तरह की गड़बड़ी की शिकायत, Compose Runtime कॉम्पोनेंट को करें.