--split-debug-info(--obfuscateの有無にかかわらず)を使用してFlutterアプリをビルドする場合、アプリが報告するDartのスタックトレースには、関数名、ファイル名、行番号の代わりにメモリアドレスが含まれます。そのビルドに一致するデバッグシンボルファイルを提供すると、New Relicはブラウザでこれらのスタックトレースをシンボル化できます。ブラウザ内でのシンボル化は、処理された例外にのみ適用されます。
このページでは、以下について説明します:
- シンボリケーションが必要な場合
- シンボルファイルの生成方法
- New Relic UIでスタックトレースをシンボル化する方法
- Flutter CLIを使用してローカルでシンボル化する方法
- リリースした任意のバージョンのエラーをシンボル化できるようにシンボルファイルを保存する方法
重要
シンボリケーションは完全にブラウザ内で実行されます。New Relicは、シンボルファイルやシンボリケーションされたスタックトレースをアップロード、保存、または保持しません。結果はエラー間でも共有されません:開いたエラーごとに個別にシンボルファイルをアップロードし、ページをリロードしたり、後で戻ってきたりするたびに再度アップロードします。毎回ファイルが必要になるため、すべてのリリースでシンボルファイルを保持してください。
シンボリケーションが必要な場合
この表は、リリースのビルド方法に基づいて、シンボリケーションが必要になるタイミングを示しています:
| リリースのビルド方法 | Dartのスタックトレースの表示内容 | シンボリケーションが必要ですか? |
|---|---|---|
flutter build なし --split-debug-info | 読みやすい関数名とファイル名 | いいえ |
flutter build --split-debug-info=<dir> | メモリアドレス(abs、virt)と build_id | はい |
flutter build --obfuscate --split-debug-info=<dir> | メモリアドレス、および名前が表示される箇所の難読化された名前 | はい |
シンボル化されていないDartのスタックトレースは次のようになります:
*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***pid: 24564, tid: 532322394208, name 1.uios: android arch: arm64 comp: yes sim: nobuild_id: '7a3ef930539e62583fa36f07eb2df79c'isolate_dso_base: 7887a27000, vm_dso_base: 7887a27000isolate_instructions: 7887b1da40, vm_instructions: 7887b07000 #00 abs 0000007887d2ea63 virt 0000000000307a63 _kDartIsolateSnapshotInstructions+0x211023 #01 abs 0000007887d39077 virt 0000000000312077 _kDartIsolateSnapshotInstructions+0x21b637 #02 abs 0000007887b2d2cf virt 00000000001062cf _kDartIsolateSnapshotInstructions+0xf88f #03 abs 0000007887d38eeb virt 0000000000311eeb _kDartIsolateSnapshotInstructions+0x21b4abNew Relic UIでは、これらの各行はスタックトレース内の個別の行として表示され、unparsedというラベルが付けられます。
スタックトレースヘッダーを理解する
トレースの最初の6行はスタックフレームではありません。これらは、Dartランタイムがすべてのシンボル化されていないトレースの先頭に書き込む、プロセスとビルドに関するメタデータです:
| 折れ線グラフ | その意味 |
|---|---|
*** *** *** ... | シンボル化されていないDartスタックトレースの開始を示します。 |
pid: 24564, tid: 532322394208, name 1.ui | エラーが発生したプロセスID、スレッドID、およびスレッド名。1.uiはFlutterのUIスレッドです。New Relic UIでは、これはThread列にも表示されます。 |
os: android arch: arm64 comp: yes sim: no | デバイスのOSとCPUアーキテクチャー。comp: yesはコードが事前コンパイルされたこと(リリースビルド)を意味し、sim: noはシミュレーターではなく物理デバイスで実行されたことを意味します。適切なシンボルファイルを選択するには、archを使用してください。 |
build_id: '7a3ef930...' | エラーを生成したビルドのユニークID。アップロードするシンボルファイルは、同じビルドIDを持つ必要があります。 |
isolate_dso_base, vm_dso_base | アプリのコンパイル済みDartコードがデバイスにロードされたメモリアドレス。 |
isolate_instructions, vm_instructions | コンパイルされたDart命令が開始されるメモリアドレス。 |
アプリを実行するたびにアドレス値は変わるため、同じエラーが2回発生しても異なる値が表示されることがあります。シンボリケーションは、ビルドIDとこれらのアドレスを使用して、各フレーム(#00、#01、...)のソースの場所を特定します。
ヘッダー行はコード位置ではないため、シンボル化されることはありません。シンボルファイルをアップロードする前後でunparsedというラベルが付けられたままであり、エラーをエクスポートする際にも変更されずに含まれます。その下にある番号付きフレームのみが変更されます。
Flutterのシンボルファイルを理解する
Flutterアプリはコンパイルされたコードの複数のレイヤーで構成されており、各レイヤーには独自のデバッグシンボルファイルがあります。各ファイルは自身のレイヤーからのエラーのみをシンボリケーションするため、Flutterリリースでは複数のシンボルファイルが生成されます:
| ファイル | プラットフォーム | シンボル化されるもの | 作成される場所 | New Relicでの使用方法 |
|---|---|---|---|---|
.symbols (Dartデバッグ情報) | Android、iOS | FlutterコードからのDartエラー | に渡すディレクトリ --split-debug-info | このページで説明されているように、ブラウザでアップロードします |
mapping.txt (R8/ProGuardマッピング) | Android | Androidのクラッシュにおける難読化されたJavaおよびKotlinコード | build/app/outputs/mapping/release/ | ProGuardまたはDexGuardの設定 |
native-debug-symbols.zip (ELFシンボル) | Android | Flutterエンジン(libflutter.so)を含む、ネイティブ(C/C++)フレーム | build/app/outputs/native-debug-symbols/release/ | ネイティブクラッシュレポート |
.dSYM | iOS | ネイティブiOSのクラッシュ:Runner、Flutterエンジン、App.framework、およびネイティブプラグイン | build/ios/Release-iphoneos/ flutter build iosの後、またはbuild/ios/archive/Runner.xcarchive/dSYMs/の後 flutter build ipa | dSYMファイルをアップロードする |
New Relicは、Dartエラーをシンボリケートするために.symbolsファイルのみを使用します。dSYM、mapping.txt、またはnative-debug-symbols.zipをDartエラーにアップロードしても、シンボリケートされません。ただし、リリースが報告するあらゆる種類のエラーをシンボリケートできるように、リリースごとにそれらをすべて保持してください。
シンボルファイルの生成
リリースをビルドする際、Flutterはシンボルファイルを作成します。すでに出荷されたビルドに対して、後からこれらを作成することはできません。
〜を使用したビルド --split-debug-info
リリースビルドコマンドに--split-debug-infoを追加してください。異なるリリースのシンボルファイルが互いに上書きされないように、バージョンごとに別々の出力ディレクトリを使用することをお勧めします:
$# Android App Bundle$flutter build appbundle --release --obfuscate --split-debug-info=build/symbols/1.4.2+57$
$# Android APK$flutter build apk --release --obfuscate --split-debug-info=build/symbols/1.4.2+57$
$# iOS (App Store / TestFlight archive)$flutter build ipa --release --obfuscate --split-debug-info=build/symbols/1.4.2+57$
$# iOS (app bundle only)$flutter build ios --release --obfuscate --split-debug-info=build/symbols/1.4.2+57--obfuscate はオプションですが、使用する場合は--split-debug-infoも使用する必要があります。
出力ファイルの検索
ビルドは、--split-debug-infoに渡したディレクトリ(たとえばbuild/symbols/1.4.2+57/)に.symbolsファイルを書き込みます。Flutterはそれらを他の場所に配置しないため、フラグを省略したり、そのディレクトリを削除したりすると、ファイルは失われます。ビルドがコンパイルされた各CPUアーキテクチャーにつき1つのファイルがあります:
| プラットフォーム | ファイル |
|---|---|
| Android | app.android-arm64.symbols、 app.android-arm.symbols 、 app.android-x64.symbols |
| iOS | app.ios-arm64.symbols |
単一のApp BundleまたはAPKには複数のアーキテクチャーのコードが含まれているため、Androidビルドは複数のファイルを生成します。各デバイスはそのうちの1つだけを実行するため、すべてを保持してください。--target-platform(たとえば--target-platform android-arm64)を使用してビルドすると、リストしたプラットフォームのファイルのみが取得されます。
Flutterのリリースビルドはシミュレーターではなく、物理的なarm64デバイスでのみ実行されるため、iOSビルドはapp.ios-arm64.symbolsのみを生成します。これは、そのiOSビルドからのすべてのDartエラーに対してアップロードするファイルです。
Androidビルドはmapping.txtとnative-debug-symbols.zipも作成し、iOSビルドはdSYMファイルも作成します。これらはDartのエラーには使用されません。「Flutterのシンボルファイルについて」を参照してください。
New Relicでスタックトレースをシンボリケートする
エラーを開く
いずれかの場所からDartエラーを開いてください:
- one.newrelic.com > Errors Inbox、次にエラーを選択します。
- one.newrelic.com > Mobile > (select your app) > Handled exceptions、次にエラーを選択します。
Stack traceセクションまでスクロールします。
エラーのappVersionとappBuildを確認してください。これらにより、どのリリースのシンボルファイルが必要かがわかります。
一致するシンボルファイルをアップロードする
スタックトレースの上にあるNot seeing what you expected?バナーでは、オンデマンドのシンボル化を利用できます。Upload .symbols fileをクリックし、エラーのビルドIDとアーキテクチャーに一致する.symbolsファイルを選択します。

シンボリケーション前は、すべての行にunparsedというラベルが付けられます。
結果を確認またはエクスポートする
シンボリケーションが完了すると、バナーがSymbolicated your traceに変わり、解決されたフレーム数(例:Symbolicated 4 of 4 unresolved frames)が報告されます。解決された各フレームには、ファイル、行番号、関数が表示されるようになります(例:main.dart line 81 in ._testFetch())。
最初の6行(スタックトレースヘッダー)は、unparsedというラベルのままです。これは想定された動作です:これらはプロセスとビルドに関するメタデータであり、コードの場所ではありません。

シンボル化後、番号付きフレームはファイル、行、および関数に解決されます。ヘッダー行はunparsedのままです。
結果はページが開いている間のみ保持されます。保持するには、Export handled exception detailsをクリックします。エクスポートにはシンボル化されたフレームが含まれるため、チケットに添付したり、チームと共有したりできます。
別のエラーをシンボル化するには、そのエラーを開き、シンボルファイルを再度アップロードしてください。1つのエラーの結果は、他のエラーには引き継がれません。
適切なシンボルファイルを見つける
各シンボルファイルは、1つのビルドと1つのCPUアーキテクチャーにのみ属します。これらを使用して、正しいファイルを選択します:
リリース:エラーの
appVersionおよびappBuildを、そのリリース用に保存したシンボルフォルダーと一致させてください。アーキテクチャー:スタックトレースヘッダーの
arch行目をファイル名と一致させます。たとえば、Androidでのarch: arm64はapp.android-arm64.symbolsを意味します。最新のAndroidスマートフォンのほとんどはarm64です。古いデバイスや低価格のデバイスはarmである場合があります。ビルドID:スタックトレース内の
build_idは、シンボルファイル内のビルドIDと一致する必要があります。Androidのシンボルファイルの場合、macOSまたはLinuxでfileコマンドを使用してビルドIDを読み取ることができます。これはBuildIDの値です:bash$file app.android-arm64.symbols$# app.android-arm64.symbols: ELF 64-bit LSB shared object, ARM aarch64, ..., BuildID[md5/uuid]=7a3ef930539e62583fa36f07eb2df79c, with debug_info, not strippediOSシンボルファイルでは
fileの出力にBuildIDが表示されないため、iOSの場合は、リリースと、ファイルをアップロードする際にNew Relicが実行するチェックを頼りにしてください。
New Relicは、AndroidとiOSの両方のエラーについて、ビルドIDを確認します。異なるビルドのシンボルファイルをアップロードした場合、New Relicはフレームをシンボル化できず、ファイルのビルドIDがトレースのビルドと一致しないというメッセージとともにWe couldn't symbolicate this traceが表示されます。エラーが発生した正確なビルドのファイルをアップロードしてください。

一致しないシンボルファイルを使用すると、フレームは解決されません。
注意
再ビルドで同じビルドIDが生成されるのは、ソースコード、依存関係、Flutterのバージョン、およびビルドフラグがすべて完全に同じである場合のみです。少しでも違いがあると新しいビルドIDが生成され、新しいシンボルファイルは一致しなくなります。実際に出荷したビルドのシンボルファイルを保存してください。後から再作成できるとは限らないため、ご注意ください。
次を使用してローカルでシンボリケートする flutter symbolize
New Relic UIを使用できない場合、またはスクリプトで多くのトレースをシンボル化したい場合は、代わりにFlutter CLIを使用できます:
ヘッダー行(
*** *** ***、pid、os/arch、build_id、isolate_dso_base、およびisolate_instructions)を含めてエラーからスタックトレースをコピーし、たとえばtrace.txtなどのファイルに保存してください。一致するシンボルファイルを使用して
flutter symbolizeを実行します:bash$flutter symbolize \>--input=trace.txt \>--debug-info=build/symbols/1.4.2+57/app.android-arm64.symbols \>--output=trace-symbolicated.txt長い
--debug-infoオプションを使用してください。Flutterのグローバルオプションの中で、-dは"device"を意味するため、短い形式は混同されやすくなります。
ベストプラクティス:すべてのリリースでシンボルを保存する
New Relicはシンボルファイルを保持しないため、ご自身で保存する必要があります。エラーが発生した後ではなく、各リリースをビルドする際に保存してください:すでに出荷したビルド用に再作成することはできません。
- 内部ビルド、ベータビルド、およびストアビルドを含め、配布するすべてのビルドのシンボルファイルを保持してください。
.symbolsファイルだけでなく、すべての種類のシンボルファイルを保持してください。「Flutterシンボルファイルについて」を参照してください。- 各ビルドのすべてのアーキテクチャーを保持してください。
- エラーに対して適切なファイルを見つけられるように、アプリが報告する
appVersionおよびappBuild属性に合わせて、バージョンとビルド番号でラベル付けしてください。 - そのバージョンが使用されている間は、それらを保持してください。ユーザーは何ヶ月も古いバージョンを使い続けることがよくあります。
- アクセスを制限します。シンボルファイルはコードの構造を明らかにします。ソースコードと同じアクセス制御で保存してください。
どこに保存するかは任意です。たとえば、CIシステムのビルドアーティファクト、ストレージバケット、アーティファクトリポジトリなどです。CIビルドアーティファクトを使用する場合は、CIシステムがそれらを保持する期間を確認してください。多くのシステムでは、一定時間後に自動的に削除されるためです。