Pembangunan Aplikasi Mudah Alih Flutter · Pelajaran

Pelaporan Ranap dan Jejak Timbunan Bersimbol

Sepadukan Crashlytics dan Sentry dengan pemetaan nyahkabur untuk laporan ranap yang boleh diambil tindakan.

Pelajaran 3 daripada 413 langkah

Pelaporan Ranap dan Jejak Timbunan Bersimbol ialah pelajaran Pembangunan Aplikasi Mudah Alih Flutter percuma di CoddyKit. Ini ialah pelajaran 3 daripada 4. Sebanyak 3 pelajaran dalam laluan pembelajaran ini boleh dibaca sepenuhnya secara percuma — selepas itu, CoddyKit PRO membuka akses kepada semua pelajaran, serta latihan praktikal dengan penyunting kod terbina dalam dan tutor kecerdasan buatan yang tersedia 24/7. Pelajaran ini merupakan sebahagian daripada laluan pembelajaran Pembangunan Aplikasi Mudah Alih Flutter, dan kemajuan anda disegerakkan merentas web serta aplikasi CoddyKit. Kursus Pembangunan Aplikasi Mudah Alih Flutter merangkumi sejumlah 4 pelajaran.

Mengapa Jejak Ranap Mentah Tidak Berguna

Apabila anda menghantar aplikasi Flutter dalam mod keluaran, pengompil Dart menghasilkan kod mesin AOT yang dioptimumkan dan membuang simbol yang boleh dibaca manusia. Ranap yang berlaku dalam pengeluaran tidak lagi melaporkan UserRepository.fetchProfile — sebaliknya melaporkan ofset heks seperti #00 abs 0000007f9c2a1b40.

  • Binaan nyahpepijat mengekalkan simbol, jadi jejak boleh dibaca secara setempat.
  • Binaan keluaran melakukan pengaburan dan pembuangan simbol, jadi jejak pada peranti hanya mengandungi alamat.
  • Untuk menukar alamat tersebut kembali kepada nama kaedah, anda memerlukan simbolikasi (simbol asli iOS/Android) dan penyahkaburan (pemetaan simbol Dart).

Pelajaran ini menyediakan Crashlytics dan Sentry supaya setiap ranap pengeluaran tiba dengan simbolikasi lengkap dan boleh diambil tindakan.

Pengaburan dan Fail Peta Simbol

Pengaburan Flutter ialah pilihan yang perlu diaktifkan. Anda mengaktifkannya pada masa binaan dan Flutter menulis peta simbol Dart bagi setiap seni bina sasaran ke dalam direktori yang anda pilih.

  • --obfuscate menamakan semula pengecam Dart kepada token pendek.
  • --split-debug-info menulis fail pemetaan, contohnya app.android-arm64.symbols, supaya anda boleh menyahbalikkan pengaburan kemudian.

Anda mesti mengarkibkan fail simbol ini bagi setiap keluaran. Tanpa fail tepat yang sepadan dengan binari yang dihantar, jejak itu tidak boleh dinyahkaburkan.

# Build an obfuscated Android release and keep the Dart symbols
flutter build appbundle --release \
  --obfuscate \
  --split-debug-info=build/symbols/v1.4.0

# iOS equivalent
flutter build ipa --release \
  --obfuscate \
  --split-debug-info=build/symbols/v1.4.0

Dua Lapisan: Simbol Asli berbanding Dart

Laporan ranap Flutter mempunyai dua masalah simbolikasi yang berbeza, dan kekeliruan antara kedua-duanya ialah sebab utama jejak kekal tidak boleh dibaca.

  • Lapisan asli (dSYM iOS, simbol .so Android NDK): menyelesaikan ranap dalam enjin, pemalam dan kod platform. Dikendalikan oleh muat naik simbol asli Crashlytics.
  • Lapisan Dart (fail --split-debug-info): menyelesaikan ranap dalam logik perniagaan Dart anda selepas pengaburan.

Crashlytics menyimbolikakan bingkai asli secara automatik selepas anda memuat naik dSYM/simbol NDK, tetapi bingkai Dart masih memerlukan fail simbol Flutter diproses melalui flutter symbolize.

Memulakan Firebase Crashlytics

Crashlytics mesti dimulakan sebelum runApp dan disambungkan kepada cangkuk ralat Flutter supaya tiada apa-apa terlepas.

  • FlutterError.onError menangkap ralat segerak rangka kerja.
  • PlatformDispatcher.instance.onError menangkap ralat tak segerak yang terlepas daripada zon.

Menghalakan kedua-duanya ke recordFlutterFatalError / recordError memastikan setiap ralat Dart yang tidak ditangkap sampai ke Crashlytics.

import 'dart:ui';
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_crashlytics/firebase_crashlytics.dart';
import 'package:flutter/material.dart';

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp();

  final crashlytics = FirebaseCrashlytics.instance;
  FlutterError.onError = crashlytics.recordFlutterFatalError;
  PlatformDispatcher.instance.onError = (error, stack) {
    crashlytics.recordError(error, stack, fatal: true);
    return true;
  };

  runApp(const MyApp());
}

Memuat Naik Simbol Asli ke Crashlytics

Untuk bingkai asli, Crashlytics memerlukan fail simbol binaan dimuat naik ke Firebase.

  • iOS: skrip FirebaseCrashlytics memuat naik dSYM; untuk bitcode atau dSYM yang tiada, gunakan alat upload-symbols.
  • Android: pemalam Gradle firebase-crashlytics memuat naik simbol NDK apabila nativeSymbolUploadEnabled ialah benar.

Muat naik ini berlaku pada masa binaan/keluaran, bukan pada masa pelaksanaan, jadi proses ini perlu diletakkan dalam saluran paip CI anda.

// android/app/build.gradle
plugins {
    id 'com.google.firebase.crashlytics'
}

android {
    buildTypes {
        release {
            firebaseCrashlytics {
                // Upload Android NDK native symbols
                nativeSymbolUploadEnabled true
                unstrippedNativeLibsDir 'build/app/intermediates/merged_native_libs'
            }
        }
    }
}

Menyahkaburkan Bingkai Dart dengan flutter symbolize

Crashlytics tidak dapat membaca peta Dart --split-debug-info anda. Apabila bingkai Dart bagi sesuatu ranap memaparkan token yang dikaburkan, anda mengeksport jejak mentah dan memprosesnya melalui alat SDK Flutter.

  • flutter symbolize menerima jejak tindanan yang dikaburkan bersama fail simbol tepat untuk ABI dan versi tersebut.
  • Output menggantikan ofset heks dan token pendek dengan nama kaedah Dart serta nombor baris sebenar.

Inilah sebabnya direktori simbol bagi setiap keluaran mesti diarkibkan — anda memerlukan fail yang sepadan dengan binaan yang mengalami ranap.

# stack.txt holds the obfuscated trace copied from Crashlytics
flutter symbolize \
  -i stack.txt \
  -d build/symbols/v1.4.0/app.android-arm64.symbols

# Output now shows real frames, e.g.:
#   #00  UserRepository.fetchProfile (package:app/data/user_repository.dart:42)

Menambahkan Sentry Bersama Crashlytics

Sentry ialah alternatif atau pelengkap yang popular kepada Crashlytics. SDK Flutter membalut aplikasi anda dan menangkap ralat yang tidak dikendalikan secara automatik, tetapi nilai sebenar terletak pada saluran paip simbol nyahpepijat.

  • SentryFlutter.init memasang integrasi dan membolehkan anda menetapkan pensampelan, keluaran dan persekitaran.
  • Membalut runApp dalam appRunner memastikan pengendali ralat peringkat zon aktif.

Tetapkan rentetan release kepada name+buildNumber supaya Sentry dapat memadankan ranap dengan simbol yang dimuat naik dan betul.

import 'package:flutter/material.dart';
import 'package:sentry_flutter/sentry_flutter.dart';

Future<void> main() async {
  await SentryFlutter.init(
    (options) {
      options.dsn = 'https://examplePublicKey@o0.ingest.sentry.io/0';
      options.tracesSampleRate = 0.2;
      options.environment = 'production';
      options.release = 'com.coddykit.app@1.4.0+140';
    },
    appRunner: () => runApp(const MyApp()),
  );
}

Memuat Naik Simbol Nyahpepijat ke Sentry

Sentry menyahkaburkan secara automatik di sisi pelayan selepas anda memuat naik artifak yang betul dengan sentry-cli (atau pemalam Dart Sentry semasa binaan).

  • Muat naik fail nyahpepijat asli dSYM / ELF melalui debug-files upload.
  • Muat naik simbol Dart Flutter, iaitu output --split-debug-info, supaya bingkai Dart yang dikaburkan dapat diselesaikan.

Oleh sebab Sentry memadankan berdasarkan ID nyahpepijat dan keluaran, muat naik daripada CI mesti menggunakan direktori --split-debug-info yang sama seperti yang menghasilkan binari yang dihantar.

# Upload native + Dart debug information files for this release
sentry-cli debug-files upload \
  --org coddykit --project flutter-app \
  build/symbols/v1.4.0

# Associate the release so Sentry can match incoming events
sentry-cli releases new com.coddykit.app@1.4.0+140
sentry-cli releases finalize com.coddykit.app@1.4.0+140

Memperkaya Laporan dengan Konteks dan Serpihan Jejak

Jejak yang telah dipetakan simbol memberitahu anda di mana; konteks memberitahu anda mengapa. Kedua-dua SDK membolehkan anda melampirkan metadata supaya sesuatu ranap dapat dihasilkan semula.

  • Kunci tersuai: bendera ciri, tahap pengguna, laluan semasa.
  • Jejak serbuk roti / pengelogan: rekod tindakan terkini yang membawa kepada ranap.
  • Pengecam pengguna: untuk menganggarkan bilangan pengguna yang terjejas oleh sesuatu ranap.

Jangan sekali-kali log PII. Gunakan ID legap dan bendera yang berkaitan dengan ciri sahaja.

Future<void> tagCrashContext(FirebaseCrashlytics c) async {
  await c.setUserIdentifier('user_8f3a');
  await c.setCustomKey('subscription', 'pro');
  await c.setCustomKey('active_route', '/checkout');
  await c.log('Tapped Pay button with cart total 49.99');
}

Merekod Ralat yang Dikendalikan (Tidak Maut)

Tidak semua ralat sepatutnya menyebabkan apl ranap. Panggilan rangkaian yang gagal atau ralat penghuraian yang ditangkap ialah peristiwa tidak maut yang masih perlu anda pantau.

  • Crashlytics: recordError(e, st, fatal: false).
  • Sentry: Sentry.captureException(e, stackTrace: st).

Contoh Dart kendiri ini menunjukkan corak tangkap-dan-laporkan yang akan anda salurkan kepada mana-mana SDK dari lapisan perkhidmatan.

void reportHandled(Object error, StackTrace stack) {
  // In production this would call recordError / captureException.
  print('NON-FATAL: $error');
  print('Top frame: ${stack.toString().split('\n').first}');
}

Map<String, dynamic> parseProfile(String raw) {
  if (!raw.startsWith('{')) {
    throw const FormatException('Profile payload is not JSON');
  }
  return {'ok': true};
}

void main() {
  try {
    parseProfile('not-json');
  } catch (e, st) {
    reportHandled(e, st);
  }
  print('App keeps running after handled error');
}

Menjadikan Muat Naik Simbol Sebahagian daripada CI

Punca terbesar ranap pengeluaran yang tidak boleh dibaca ialah proses keluaran yang rosak: seseorang menghantar binaan tetapi terlupa memuat naik atau mengarkibkan simbolnya. Automatikkan proses ini.

  • Bina dengan --obfuscate --split-debug-info=build/symbols/$VERSION.
  • Muat naik simbol natif (pemalam Gradle Crashlytics / skrip pelaksanaan iOS) dan simbol Dart (sentry-cli) dalam kerja CI yang sama.
  • Kekalkan build/symbols/$VERSION sebagai artifak CI untuk tempoh selama versi tersebut boleh mengalami ranap di lapangan.

Ikat rentetan versi yang digunakan di semua tempat — Sentry release, Crashlytics setCustomKey, dan nama direktori simbol — kepada satu sumber kebenaran supaya padanan tidak pernah tersasar.

# CI snippet (bash) — one job that builds and ships symbols
VERSION=$(grep '^version:' pubspec.yaml | awk '{print $2}')

flutter build appbundle --release \
  --obfuscate --split-debug-info=build/symbols/$VERSION

# Dart + native symbols to Sentry
sentry-cli debug-files upload --org coddykit --project flutter-app \
  build/symbols/$VERSION

# Keep the map for later flutter symbolize runs
tar -czf symbols-$VERSION.tgz build/symbols/$VERSION

Semakan Pantas: Mengapa Bingkai Dart Kekal Terkabur

Anda menghantar keluaran Flutter yang dibina dengan --obfuscate --split-debug-info. Bingkai natif dalam Crashlytics boleh dibaca, tetapi bingkai Dart dalam logik perniagaan anda masih memaparkan token pendek dan ofset heks. Apakah pembaikan yang betul?

Imbas Kembali: Saluran Paip Ranap yang Boleh Diambil Tindakan

Kini anda mempunyai saluran paip hujung ke hujung yang menukarkan ranap pengeluaran yang sukar difahami kepada laporan pepijat yang boleh dibaiki.

  • Bina keluaran dengan --obfuscate --split-debug-info=build/symbols/$VERSION dan arkibkan direktori itu bagi setiap keluaran.
  • Tangkap melalui FlutterError.onError + PlatformDispatcher.onError (Crashlytics) dan/atau SentryFlutter.init dengan appRunner.
  • Petakan simbol untuk dua lapisan: natif (muat naik dSYM/NDK) dan Dart (flutter symbolize untuk Crashlytics, secara automatik pada pelayan untuk Sentry selepas simbol dimuat naik).
  • Perkayakan dengan ID pengguna, kunci tersuai dan jejak serbuk roti — tanpa PII.
  • Automatikkan muat naik simbol dalam CI dan kekalkan satu rentetan versi sebagai satu-satunya sumber kebenaran.

Peraturan emas: laporan ranap hanya sebaik fail simbol yang anda simpan untuk binaan tepat tersebut.

Percuma untuk bermula

Pelajari Dart dengan tutor kecerdasan buatan — percuma

Tulis dan jalankan kod sebenar dalam pelayar anda, dapatkan bantuan segera daripada tutor kecerdasan buatan yang tersedia 24/7, dan sambung semula dari tempat anda berhenti di web atau dalam aplikasi.

Kursus
22
Pelajaran
88

Soalan Lazim

Adakah pelajaran “Pelaporan Ranap dan Jejak Timbunan Bersimbol” percuma?

Ya — sebanyak 3 pelajaran dalam laluan pembelajaran Pembangunan Aplikasi Mudah Alih Flutter, termasuk “Pelaporan Ranap dan Jejak Timbunan Bersimbol”, boleh dibaca sepenuhnya secara percuma di web ini. Selepas itu, CoddyKit PRO membuka akses kepada semua pelajaran, serta latihan interaktif dengan penyunting kod terbina dalam dan tutor kecerdasan buatan yang tersedia 24/7. Kursus Pembangunan Aplikasi Mudah Alih Flutter merangkumi sejumlah 4 pelajaran.

Apakah yang akan saya pelajari dalam “Pelaporan Ranap dan Jejak Timbunan Bersimbol”?

Sepadukan Crashlytics dan Sentry dengan pemetaan nyahkabur untuk laporan ranap yang boleh diambil tindakan. Anda berlatih Pembangunan Aplikasi Mudah Alih Flutter menggunakan kod praktikal yang dijalankan terus dalam pelayar, manakala tutor kecerdasan buatan 24/7 menjawab soalan anda semasa anda mengikuti pelajaran.

Adakah saya memerlukan pengalaman untuk memulakan Pembangunan Aplikasi Mudah Alih Flutter?

Tiada pengalaman terdahulu diperlukan. Pembelajaran Pembangunan Aplikasi Mudah Alih Flutter di CoddyKit disusun untuk pelajar daripada peringkat pemula hingga lanjutan, jadi anda boleh bermula di sini atau dari awal dan belajar mengikut kadar anda sendiri. Ini ialah pelajaran 3 daripada 4.

Berapa lamakah pelajaran “Pelaporan Ranap dan Jejak Timbunan Bersimbol” diambil?

Kebanyakan pelajaran CoddyKit mengambil masa kira-kira 5–10 minit. Setiap pelajaran ringkas dan interaktif, jadi anda boleh membuat kemajuan secara berterusan dan menyambung tepat dari tempat anda berhenti di web atau aplikasi.

Bolehkah saya menulis dan menjalankan kod dalam pelajaran Pembangunan Aplikasi Mudah Alih Flutter ini?

Ya. Setiap pelajaran Pembangunan Aplikasi Mudah Alih Flutter menyertakan penyunting kod terbina dalam, jadi anda boleh menulis dan menjalankan kod sebenar terus dalam pelayar serta menerima maklum balas kecerdasan buatan serta-merta — tanpa memerlukan persediaan setempat.

Semua pelajaran dalam kursus ini

  1. Variasi Binaan dan Konfigurasi Persekitaran
  2. Saluran Automatik dengan Fastlane dan GitHub Actions
  3. Pelaporan Ranap dan Jejak Timbunan Bersimbol
  4. Konfigurasi Jauh, Bendera Ciri dan Pelancaran Berperingkat
← Kembali ke Pembangunan Aplikasi Mudah Alih Flutter