1. 概要
この Codelab では、機能のロールアウト中にアプリのパフォーマンスをモニタリングする方法を学びます。このサンプルアプリには基本的な機能があり、Firebase Remote Config フラグに基づいて異なる背景画像が表示されるように設定されています。トレースの計測を使用してアプリのパフォーマンスをモニタリングし、アプリに構成変更をロールアウトしてその影響をモニタリングし、パフォーマンスを改善する方法を学びます。
学習内容
- Firebase Performance Monitoring をモバイルアプリに追加して、すぐに使用できる指標(アプリの起動時間、フレームの遅延やフリーズなど)を取得する方法
- カスタム トレースを追加してユーザー ジャーニーのクリティカル コードパスを把握する方法
- Performance Monitoring ダッシュボードを使用して指標を理解し、機能のロールアウトなどの重要な変更を追跡する方法
- パフォーマンス アラートを設定して主要な指標をモニタリングする方法
- Firebase Remote Config の変更をロールアウトする方法
前提条件
- Android Studio 4.0 以降
- API レベル 16 以降を搭載した Android Emulator。
- Java バージョン 8 以降
- Firebase Remote Config の基本知識
2. サンプル プロジェクトをセットアップする
コードをダウンロードする
次のコマンドを実行して、この Codelab のサンプルコードのクローンを作成します。これにより、マシンに codelab-perf-rc-android
というフォルダが作成されます。
$ git clone https://github.com/FirebaseExtended/codelab-feature-rollout-performance.git
マシンに Git がない場合は、GitHub から直接コードをダウンロードすることもできます。
firebase-perf-rc-android-start
フォルダのプロジェクトを Android Studio にインポートします。ランタイム例外が表示されたり、google-services.json
ファイルがないことを示す警告が表示されたりする可能性があります。これは次のセクションで修正します。
この Codelab では、Firebase Assistant プラグインを使用して Android アプリを Firebase プロジェクトに登録し、必要な Firebase 構成ファイル、プラグイン、依存関係を Android プロジェクトに追加します。これらはすべて、Android Studio 内から行えます。
アプリを Firebase に接続する
- [Android Studio] / [Help] >Android Studio と Firebase Assistant の最新バージョンを使用していることを確認するために、アップデートを確認してください。
- [ツール] >[Firebase] をクリックして [Assistant] ペインを開きます。
- [Performance Monitoring] を選択してアプリに追加し、[Performance Monitoring を使ってみる] をクリックします。
- [Connect to Firebase] をクリックして Android プロジェクトを Firebase に接続します。(ブラウザで Firebase コンソールが開きます)
- Firebase コンソールで [プロジェクトを追加] をクリックし、Firebase プロジェクト名を入力します(すでに Firebase プロジェクトがある場合は、代わりにその既存のプロジェクトを選択できます)。[続行] をクリックして利用規約に同意し、Firebase プロジェクトと新しい Firebase アプリを作成します。
次に、新しい Firebase アプリを Android Studio プロジェクトに接続するためのダイアログが表示されます。
- [接続] をクリックします。
- Android Studio を開きます。[Assistant] ペインに、アプリが Firebase に接続したことの確認が表示されます。
アプリに Performance Monitoring を追加する
Android Studio の [Assistant] ペインで、[Add Performance Monitoring to your app] をクリックします。
[Accept Changes] ダイアログが表示されます。この後、必要な依存関係がすべて追加されていることを確認するために、Android Studio がアプリを同期します。
最後に、Android Studio の [Assistant] ペインに、すべての依存関係が正しく設定されていることを示す成功メッセージが表示されます。
追加の手順として、「(省略可)デバッグ ロギングを有効にする」の手順に沿ってデバッグ ロギングを有効にします。同じ手順が一般公開ドキュメントにも記載されています。
3. アプリを実行する
アプリのモジュール(アプリレベル)ディレクトリに google-services.json
ファイルが表示され、アプリがコンパイルされます。Android Studio で、[Run] > [Run 'アプリ'] をクリックして、Android エミュレータでアプリをビルドして実行します。
アプリを実行すると、最初に次のようなスプラッシュ画面が表示されます。
数秒後、デフォルトの画像を含むメインページが表示されます。
仕組み
スプラッシュ画面は SplashScreenActivity に実装されており、次の処理を行います。
onCreate()
では、Firebase Remote Config の設定を初期化し、この Codelab の後半で Remote Config ダッシュボードで設定する設定値を取得します。executeTasksBasedOnRC()
で、seasonal_image_url
フラグの構成値を読み取ります。config 値で URL が指定されている場合は、画像が同期的にダウンロードされます。- ダウンロードが完了すると、アプリは MainActivity に移動し、
finish()
を呼び出してSplashScreenActivity
を終了します。
MainActivity
では、Remote Config で seasonal_image_url
が定義されている場合、この機能が有効になり、ダウンロードした画像がメインページの背景として表示されます。指定しない場合、デフォルトの画像(上記)が表示されます。
4. Remote Config を設定する
アプリが実行されるようになったので、新機能フラグを設定できます。
- Firebase コンソールの左側のパネルで [エンゲージメント] セクションに移動し、[Remote Config] をクリックします。
- [設定を作成] ボタンをクリックして設定フォームを開き、
seasonal_image_url
をパラメータキーとして追加します。 - [説明を追加] をクリックし、次のように説明を入力します。
Shows a seasonal image (replaces default) in the main page when the restaurant list is empty.
- [新しく追加] ->条件値 ->新しい条件を作成します。
- 条件名に「
Seasonal image rollout
」と入力します。 - [
Applies if...
] セクションで、[User in random percentile <= 0%
] を選択します。(後でロールアウトする準備ができるまで、この機能は無効のままにしておきます)。 - [条件を作成] をクリックします。この条件は、後でユーザーに新機能をロールアウトする際に使用します。
- [Create your first parameter form] を開き、[Value for Seasonal image rollout] フィールドを見つけます。季節の画像をダウンロードする URL「
https://images.unsplash.com/photo-1552691021-7043334e0b51
」を入力します - デフォルト値は空の文字列のままにします。つまり、URL からダウンロードした画像ではなく、コードベースのデフォルトの画像が表示されます。
- [保存] をクリックします。
新しい構成がドラフトとして作成されていることがわかります。
- [変更を公開] をクリックし、上部で変更を確認してアプリを更新します。
5. データ読み込み時間のモニタリングを追加する
お客様のアプリは、MainActivity
を表示する前に一部のデータをプリロードし、このプロセスを非表示にするスプラッシュ画面を表示します。ユーザーがこの画面で長時間待たされるのは好ましくありません。通常は、スプラッシュ画面が表示されている時間をモニタリングすることをおすすめします。
Firebase Performance Monitoring には、まさにそのための方法が用意されています。カスタムコード トレースを計測可能にすると、アプリ内の特定のコードのパフォーマンス(データの読み込み時間や新機能の処理時間など)をモニタリングできます。
スプラッシュ画面の表示時間をトラッキングするには、カスタム コード トレースを SplashScreenActivity
(スプラッシュ画面を実装する Activity
)に追加します。
splash_screen_trace
という名前のカスタムコード トレースを初期化して作成し、開始します。
SplashScreenActivity.java
// ...
import com.google.firebase.perf.FirebasePerformance;
import com.google.firebase.perf.metrics.Trace;
// ...
public class SplashScreenActivity extends AppCompatActivity {
private static final String TAG = "SplashScreenActivity";
private static final String SEASONAL_IMAGE_URL_RC_FLAG = "seasonal_image_url";
// TODO: Initialize splash_screen_trace
private final Trace splashScreenTrace = FirebasePerformance.startTrace("splash_screen_trace");
// ...
}
SplashScreenActivity
のonDestroy()
メソッドでトレースを終了します。
SplashScreenActivity.java
@Override
protected void onDestroy() {
super.onDestroy();
// TODO: Stop the splash_screen_trace here
splashScreenTrace.stop();
}
新機能では画像をダウンロードして処理するため、SplashScreenActivity
に特徴が追加された時間を追跡する 2 つ目のカスタム コード トレースを追加します。
splash_seasonal_image_processing
という名前のカスタムコード トレースを初期化して作成し、開始します。
SplashScreenActivity.java
private void executeTasksBasedOnRC(FirebaseRemoteConfig rcConfig) {
String seasonalImageUrl = rcConfig.getString(SEASONAL_IMAGE_URL_RC_FLAG);
Log.d(TAG, SEASONAL_IMAGE_URL_RC_FLAG + ": " + seasonalImageUrl);
if (!seasonalImageUrl.isEmpty()) {
// TODO: Start the splash_seasonal_image_processing here
final Trace seasonalImageProcessingTrace = FirebasePerformance
.startTrace("splash_seasonal_image_processing");
// ...
}
}
RequestListener
のonLoadFailed()
メソッドとonResourceReady()
メソッドの両方でトレースを終了します。
SplashScreenActivity.java
Glide.with(SplashScreenActivity.this.getApplicationContext())
.asBitmap()
.load(seasonalImageUrl)
.signature(new ObjectKey(Utils.getCacheUUID()))
.listener(new RequestListener<Bitmap>() {
@Override
public boolean onLoadFailed(
@Nullable GlideException e,
Object model, Target<Bitmap> target,
boolean isFirstResource) {
// TODO: Stop the splash_seasonal_image_processing here
seasonalImageProcessingTrace.stop();
launchMainActivity();
return true;
}
@Override
public boolean onResourceReady(Bitmap resource, Object model,
Target<Bitmap> target, DataSource dataSource,
boolean isFirstResource) {
// TODO: Stop the splash_seasonal_image_processing here
seasonalImageProcessingTrace.stop();
launchMainActivity();
return true;
}
})
.preload();
スプラッシュ画面の継続時間(splash_screen_trace)
と新機能の処理時間(splash_seasonal_image_processing
))を追跡するカスタム コード トレースを追加できたので、Android Studio で再度アプリを実行します。Logging trace metric: splash_screen_trace
を含むロギング メッセージが表示され、その後にトレース期間が表示されます。新しい機能をまだ有効にしていないため、splash_seasonal_image_processing
のログ メッセージは表示されません。
6. トレースにカスタム属性を追加する
カスタムコード トレースの場合、Performance Monitoring はデフォルトの属性(アプリのバージョン、国、デバイスなどの一般的なメタデータ)を自動的にログに記録するため、Firebase コンソールでトレースのデータをフィルタできます。カスタム属性を追加してモニタリングすることもできます。
アプリに 2 つのカスタムコード トレースを追加して、スプラッシュ画面の表示時間と新機能の処理時間をモニタリングしました。これらの時間に影響する要因としては、表示される画像がデフォルト画像であるか、URL からダウンロードする必要があるかなどがあります。画像をダウンロードする URL が変更される可能性もあります。
そのため、これらのカスタムコード トレースに、季節限定の画像の URL を表すカスタム属性を追加しましょう。こうすれば、後でこれらの値で期間データをフィルタできます。
splash_screen_trace
のカスタム属性(seasonal_image_url_attribute
)をexecuteTasksBasedOnRC
メソッドの先頭に追加します。
SplashScreenActivity.java
private void executeTasksBasedOnRC(FirebaseRemoteConfig rcConfig) {
String seasonalImageUrl = rcConfig.getString(SEASONAL_IMAGE_URL_RC_FLAG);
Log.d(TAG, SEASONAL_IMAGE_URL_RC_FLAG + ": " + seasonalImageUrl);
// TODO: Add a custom attribute "seasonal_image_url_attribute" to splash_screen_trace
if (seasonalImageUrl.isEmpty()) {
splashScreenTrace.putAttribute("seasonal_image_url_attribute", "unset");
} else {
splashScreenTrace.putAttribute("seasonal_image_url_attribute", seasonalImageUrl);
}
// ...
}
startTrace("splash_seasonal_image_processing")
呼び出しの直後に、splash_seasonal_image_processing
に同じカスタム属性を追加します。
SplashScreenActivity.java
if (!seasonalImageUrl.isEmpty()) {
// TODO: Start the splash_seasonal_image_processing here
final Trace seasonalImageProcessingTrace = FirebasePerformance
.startTrace("splash_seasonal_image_processing");
// TODO: Add a custom attribute "seasonal_image_url_attribute" to splash_seasonal_image_processing
seasonalImageProcessingTrace
.putAttribute("seasonal_image_url_attribute", seasonalImageUrl);
// ...
}
カスタム トレース(splash_screen_trace
と splash_seasonal_image_processing
)の両方にカスタム属性(seasonal_image_url_attribute
)を追加したので、Android Studio で再度アプリを実行します。「Setting attribute 'seasonal_image_url_attribute' to 'unset' on trace 'splash_screen_trace'.
」を含むロギング メッセージが表示されます。Remote Config のパラメータ seasonalImageUrl がまだ有効になっていません。そのため、属性値が unset
になっています。
Performance Monitoring SDK がトレースデータを収集して Firebase に送信します。データは Firebase コンソールのパフォーマンス ダッシュボードで確認できます。このダッシュボードについては、Codelab の次のステップで詳しく説明します。
7. Performance Monitoring ダッシュボードを構成する
特徴をモニタリングするようにダッシュボードを構成する
Firebase コンソールで、Friendly Eats アプリがあるプロジェクトを選択します。
左側のパネルで [リリースとMonitor セクションに移動し、[Performance] をクリックします。
指標ボードに最初のデータポイントが表示され、パフォーマンス ダッシュボードが表示されます。Performance Monitoring SDK はアプリからパフォーマンス データを収集し、収集から数分以内に表示します。
この指標ボードでは、アプリの主要な指標を追跡できます。デフォルトのビューにはアプリの起動時間のトレースの所要時間が含まれますが、最も重視する指標を追加することもできます。追加した新機能をトラッキングしているため、カスタムコード トレース splash_screen_trace
の所要時間を表示するようにダッシュボードをカスタマイズできます。
- 空の [指標を選択] ボックスのいずれかをクリックします。
- ダイアログ ウィンドウで、トレースタイプとして [カスタム トレース] を選択し、トレース名として「
splash_screen_trace
」を選択します。
- [指標を選択] をクリックすると、「
splash_screen_trace
」の長さがダッシュボードに追加されていることがわかります。
同じ手順で、重要な他の指標を追加して、時間の経過とともに、またリリースごとにパフォーマンスがどのように変化するかを簡単に確認できます。
指標ボードは、ユーザーが経験した主要な指標のパフォーマンスを追跡できる強力なツールです。この Codelab では短い期間で小規模なデータセットを使用するため、機能ロールアウトのパフォーマンスを把握するのに役立つ他のダッシュボード ビューを使用します。
8. 機能を展開する
モニタリングを設定したので、Firebase Remote Config の変更(前述の seasonal_image_url)
)をロールアウトする準備が整いました。
変更をロールアウトするには、Firebase コンソールの [Remote Config] ページに戻り、ターゲティング条件のユーザー パーセンタイルを増やします。通常、新機能はごく一部のユーザーにロールアウトし、問題がないことを確認してから対象ユーザーを拡大します。ただし、この Codelab ではアプリのユーザーのみがいるため、パーセンタイルを 100% に変更できます。
- ページの上部にある [Conditions] タブをクリックします。
- 先ほど追加した
Seasonal image rollout
条件をクリックします。 - パーセンタイル値を 100% に変更します。
- [Save Condition] をクリックします。
- [変更を公開] をクリックして、変更を確認します。
Android Studio に戻り、エミュレータでアプリを再起動して新機能を確認します。スプラッシュ画面の後に、新しい空の状態のメイン画面が表示されます。
9. パフォーマンスの変化を確認する
次に、Firebase コンソールの [Performance] ダッシュボードを使用して、スプラッシュ画面の読み込みのパフォーマンスを確認します。Codelab のこのステップでは、ダッシュボードのさまざまな部分を使用してパフォーマンス データを表示します。
- メインの [ダッシュボード] タブでトレース テーブルまで下にスクロールし、[カスタム トレース] タブをクリックします。この表には、先ほど追加したカスタムコード トレースに加えて、標準のトレースも表示されます。
- 新機能を有効にしたので、カスタム コード トレース
splash_seasonal_image_processing
を探します。このトレースは、イメージのダウンロードと処理にかかった時間を示しています。トレースの [Duration] の値を見ると、このダウンロードと処理にかなりの時間がかかることがわかります。
splash_seasonal_image_processing
のデータがあるので、[ダッシュボード] タブの上部にある指標ボードに、このトレースの期間を追加できます。
前回と同様に、空の [指標を選択] ボックスのいずれかをクリックします。ダイアログ ウィンドウで、トレースタイプ [カスタム トレース] とトレース名 [splash_seasonal_image_processing
] を選択します。最後に、[指標を選択] をクリックして、この指標を指標ボードに追加します。
- 違いをさらに確認するには、
splash_screen_trace
のデータを確認します。指標ボードでsplash_screen_trace
カードをクリックし、[指標の詳細を表示] をクリックします。
- 詳細ページの左下に、先ほど作成したカスタム属性を含む属性のリストが表示されます。カスタム属性
seasonal_image_url_attribute
をクリックすると、季節ごとの画像 URL ごとのスプラッシュ画面の再生時間が右側に表示されます。
- スプラッシュ画面の表示時間の値は、上記のスクリーンショットとは多少異なる可能性がありますが、URL から画像をダウンロードする場合は、デフォルトの画像(「unset」で表されます)を使用する場合よりも長い時間にする必要があります。
この Codelab では時間が長い理由は単純ですが、実際のアプリではそれほど明白ではないかもしれません。収集された継続時間データは、さまざまなネットワーク接続条件でアプリを実行しているさまざまなデバイスから取得されるため、これらの条件は予想よりも悪い場合があります。実際の状況でこの問題を調査する方法を見てみましょう。
- ページ上部の [パフォーマンス] をクリックして、[ダッシュボード] メインタブ に戻ります。
- ページ下部にあるトレース テーブルで、[ネットワーク リクエスト] タブをクリックします。この表には、アプリからのすべてのネットワーク リクエストが
images.unsplash.com/**
URL パターンを含めて URL パターンごとに集計されて表示されます。このレスポンス時間の値を、画像のダウンロードと処理にかかった合計時間(splash_seasonal_image_processing
トレースの所要時間)と比較すると、画像のダウンロードに多くの時間が費やされていることがわかります。
パフォーマンスに関する検出結果
Firebase Performance Monitoring を使用することで、この新機能を有効にしているエンドユーザーに次のような影響が及びました。
SplashScreenActivity
での滞在時間が長くなりました。splash_seasonal_image_processing
の時間が非常に長い。- この遅延は、画像のダウンロードの応答時間と、画像に必要な対応する処理時間によるものです。
次のステップでは、機能をロールバックしてパフォーマンスへの影響を軽減し、機能の実装を改善する方法を特定します。
10. 機能をロールバックする
スプラッシュ画面でユーザーを長く待たせることは望ましくありません。Remote Config の主なメリットの 1 つは、ユーザーに別のバージョンをリリースすることなく、ロールアウトの一時停止と取り消しができることです。これにより、問題(前のステップで見つけたパフォーマンスの問題など)にすばやく対応し、不満のあるユーザーの数を最小限に抑えることができます。
迅速な軽減策として、ロールアウトのパーセンタイルを 0
にリセットして、すべてのユーザーにデフォルトのイメージが再度表示されるようにします。
- Firebase コンソールの Remote Config ページに戻ります。
- ページの上部にある [Conditions] をクリックします。
- 先ほど追加した
Seasonal image rollout
条件をクリックします。 - パーセンタイル値を 0% に変更します。
- [Save Condition] をクリックします。
- [変更を公開] をクリックして、変更を確認します。
Android Studio でアプリを再起動すると、元の空の状態のメイン画面が表示されます。
11. パフォーマンスの問題を解決する
Codelab の前半で、スプラッシュ画面の画像のダウンロードがアプリの速度低下の原因となっていることがわかりました。ダウンロードした画像をよく見ると、画像の元の解像度で、2 MB を超えていることがわかります。パフォーマンスの問題をすばやく解決するには、画質を適切な解像度に下げて、画像のダウンロード時間を短縮します。
Remote Config の値を再度ロールアウトする
- Firebase コンソールの Remote Config ページに戻ります。
seasonal_image_url
パラメータの [編集] アイコンをクリックします。- [季節限定の画像ロールアウトの値] を
https://images.unsplash.com/photo-1552691021-7043334e0b51?w=640
に更新し、[保存] をクリックします。
- ページ上部の [条件] タブをクリックします。
- [季節に応じた画像のロールアウト] をクリックして、パーセンタイルを 100% に戻します。
- [Save Condition] をクリックします。
- [変更を公開] ボタンをクリックします。
12. 修正をテストしてアラートを設定する
アプリをローカルで実行する
新しい設定値で別の画像のダウンロード URL を使用するように設定して、アプリを再度実行します。この場合、スプラッシュ画面が表示される時間が短縮されているはずです。
変更のパフォーマンスを確認する
Firebase コンソールの [パフォーマンス] ダッシュボードに戻り、指標がどのように表示されるかを確認します。
- 今回はトレース テーブルを使用して詳細ページに移動します。トレース テーブルの下部にある [カスタム トレース] タブで、カスタム トレース
splash_seasonal_image_processing
をクリックすると、期間の指標の詳細ビューを再度表示できます。
- カスタム属性
seasonal_image_url_attribute
をクリックすると、カスタム属性の内訳を再度表示できます。URL にカーソルを合わせると、縮小サイズの画像の新しい URL と一致する値(末尾に?w=640
が付いたhttps://images.unsplash.com/photo-1552691021-7043334e0b51?w=640
)が表示されます。この画像に関連付けられた duration 値は、前の画像の値よりもかなり短く、ユーザーにとってはより許容範囲内です。
- スプラッシュ画面のパフォーマンスが向上したので、設定したしきい値をトレースが超えたときに通知するアラートを設定できます。[パフォーマンス] ダッシュボードを開き、splash_screen_trace のオーバーフロー メニュー(3 つの点)アイコンをクリックして、[アラート設定] をクリックします。
- 切り替えボタンをクリックして [Duration] アラートを有効にします。表示している値を少し上回るしきい値を設定すると、splash_screen_trace がしきい値を超えた場合にメールが届きます。
- [保存] をクリックしてアラートを作成します。トレース表までスクロールし、[カスタム トレース] タブをクリックして、アラートが有効になっていることを確認します。
13. 完了
これでFirebase Performance Monitoring SDK を有効にしてトレースを収集し、新機能のパフォーマンスを測定しました。新機能のリリースに関する主要なパフォーマンス指標をモニタリングし、パフォーマンスの問題が見つかった場合は迅速に対応しました。これらはすべて、Remote Config で構成を変更し、パフォーマンスの問題をリアルタイムでモニタリングすることで可能になりました。
学習した内容
- アプリに Firebase Performance Monitoring SDK を追加する
- コードにカスタム コード トレースを追加して特定の特徴を測定する
- 新しい機能を制御 / ロールアウトするための Remote Config パラメータと条件値を設定する
- パフォーマンス モニタリング ダッシュボードを使用してロールアウト中に問題を特定する方法
- アプリのパフォーマンスが設定したしきい値を超えたときに通知するパフォーマンス アラートを設定する